Skip to content

Commit

Permalink
Added IServiceFactory<T> + Refactor DI
Browse files Browse the repository at this point in the history
Created IServiceFactory<T> and updated all Factories to use this new interface.
Refactor test cases for dependency injectio to validate all factories using the base generic interface.
  • Loading branch information
adearriba authored and nozzlegear committed Feb 5, 2024
1 parent 5affb4d commit b8f742f
Show file tree
Hide file tree
Showing 63 changed files with 131 additions and 726 deletions.
@@ -1,4 +1,5 @@
using ShopifySharp.Utilities;
using System.Reflection;

namespace ShopifySharp.Extensions.DependencyInjection.Tests;

Expand Down Expand Up @@ -140,12 +141,35 @@ public void AddShopifySharpServiceFactories_AddsServiceFactories()

// Assert
var serviceProvider = container.BuildServiceProvider();
var orderServiceFactory = serviceProvider.GetService<IOrderServiceFactory>();

orderServiceFactory.Should()
.NotBeNull()
.And
.BeOfType<OrderServiceFactory>();
var assembly = Assembly.GetAssembly(typeof(IServiceFactory<>));

if (assembly == null)
{
throw new InvalidOperationException("No assembly found for IServiceFactory interface. Ensure you are scanning the correct assembly.");
}

var serviceFactoryTypes = assembly
?.GetTypes()
.Where(t => t.IsInterface
&& t.IsPublic
&& t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IServiceFactory<>)))
.ToList();

if (serviceFactoryTypes == null || !serviceFactoryTypes.Any())
{
throw new InvalidOperationException("No IServiceFactory interfaces found. Ensure you are scanning the correct assembly.");
}

foreach (var serviceType in serviceFactoryTypes)
{
var resolvedService = serviceProvider.GetService(serviceType);
var concreteType = assembly.GetType($"ShopifySharp.Factories.{serviceType.Name.Substring(1)}");

resolvedService.Should()
.NotBeNull()
.And
.BeOfType(concreteType);
}
}

[Fact]
Expand Down
Expand Up @@ -3,6 +3,8 @@
using Microsoft.Extensions.DependencyInjection;
using ShopifySharp.Factories;
using ShopifySharp.Utilities;
using System.Reflection;
using System.Linq;

// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable UnusedType.Global
Expand Down Expand Up @@ -79,66 +81,27 @@ public static IServiceCollection AddShopifySharpUtilities(this IServiceCollectio
public static IServiceCollection AddShopifySharpServiceFactories(this IServiceCollection services)
{
// TODO: add ServiceLifetime parameter
services.TryAddSingleton<IAccessScopeServiceFactory, AccessScopeServiceFactory>();
services.TryAddSingleton<IApplicationCreditServiceFactory, ApplicationCreditServiceFactory>();
services.TryAddSingleton<IArticleServiceFactory, ArticleServiceFactory>();
services.TryAddSingleton<IAssetServiceFactory, AssetServiceFactory>();
services.TryAddSingleton<IAssignedFulfillmentOrderServiceFactory, AssignedFulfillmentOrderServiceFactory>();
services.TryAddSingleton<IBlogServiceFactory, BlogServiceFactory>();
services.TryAddSingleton<ICancellationRequestServiceFactory, CancellationRequestServiceFactory>();
services.TryAddSingleton<ICarrierServiceFactory, CarrierServiceFactory>();
services.TryAddSingleton<IChargeServiceFactory, ChargeServiceFactory>();
services.TryAddSingleton<ICheckoutSalesChannelServiceFactory, CheckoutSalesChannelServiceFactory>();
services.TryAddSingleton<ICheckoutServiceFactory, CheckoutServiceFactory>();
services.TryAddSingleton<ICollectServiceFactory, CollectServiceFactory>();
services.TryAddSingleton<ICollectionListingServiceFactory, CollectionListingServiceFactory>();
services.TryAddSingleton<ICollectionServiceFactory, CollectionServiceFactory>();
services.TryAddSingleton<ICountryServiceFactory, CountryServiceFactory>();
services.TryAddSingleton<ICustomCollectionServiceFactory, CustomCollectionServiceFactory>();
services.TryAddSingleton<ICustomerAddressServiceFactory, CustomerAddressServiceFactory>();
services.TryAddSingleton<ICustomerSavedSearchServiceFactory, CustomerSavedSearchServiceFactory>();
services.TryAddSingleton<ICustomerServiceFactory, CustomerServiceFactory>();
services.TryAddSingleton<IDiscountCodeServiceFactory, DiscountCodeServiceFactory>();
services.TryAddSingleton<IDraftOrderServiceFactory, DraftOrderServiceFactory>();
services.TryAddSingleton<IEventServiceFactory, EventServiceFactory>();
services.TryAddSingleton<IFulfillmentEventServiceFactory, FulfillmentEventServiceFactory>();
services.TryAddSingleton<IFulfillmentOrderServiceFactory, FulfillmentOrderServiceFactory>();
services.TryAddSingleton<IFulfillmentRequestServiceFactory, FulfillmentRequestServiceFactory>();
services.TryAddSingleton<IFulfillmentServiceFactory, FulfillmentServiceFactory>();
services.TryAddSingleton<IFulfillmentServiceServiceFactory, FulfillmentServiceServiceFactory>();
services.TryAddSingleton<IGiftCardAdjustmentServiceFactory, GiftCardAdjustmentServiceFactory>();
services.TryAddSingleton<IGiftCardServiceFactory, GiftCardServiceFactory>();
services.TryAddSingleton<IGraphServiceFactory, GraphServiceFactory>();
services.TryAddSingleton<IInventoryItemServiceFactory, InventoryItemServiceFactory>();
services.TryAddSingleton<IInventoryLevelServiceFactory, InventoryLevelServiceFactory>();
services.TryAddSingleton<ILocationServiceFactory, LocationServiceFactory>();
services.TryAddSingleton<IMetaFieldServiceFactory, MetaFieldServiceFactory>();
services.TryAddSingleton<IOrderRiskServiceFactory, OrderRiskServiceFactory>();
services.TryAddSingleton<IOrderServiceFactory, OrderServiceFactory>();
services.TryAddSingleton<IPageServiceFactory, PageServiceFactory>();
var assembly = Assembly.GetAssembly(typeof(IServiceFactory<>));

var factoryTypes = assembly!.GetTypes()
.Where(t => !t.IsAbstract && !t.IsInterface)
.Where(t => t.GetInterfaces().Any(i =>
i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IServiceFactory<>)));

foreach (var type in factoryTypes)
{
var serviceType = type.GetInterfaces()
.Where(i => !i.IsGenericType)
.FirstOrDefault();

if(serviceType != null)
{
services.TryAddSingleton(serviceType, type);
}
}

services.TryAddSingleton<IPartnerServiceFactory, PartnerServiceFactory>();
services.TryAddSingleton<IPolicyServiceFactory, PolicyServiceFactory>();
services.TryAddSingleton<IPriceRuleServiceFactory, PriceRuleServiceFactory>();
services.TryAddSingleton<IProductImageServiceFactory, ProductImageServiceFactory>();
services.TryAddSingleton<IProductListingServiceFactory, ProductListingServiceFactory>();
services.TryAddSingleton<IProductServiceFactory, ProductServiceFactory>();
services.TryAddSingleton<IProductVariantServiceFactory, ProductVariantServiceFactory>();
services.TryAddSingleton<IRecurringChargeServiceFactory, RecurringChargeServiceFactory>();
services.TryAddSingleton<IRedirectServiceFactory, RedirectServiceFactory>();
services.TryAddSingleton<IRefundServiceFactory, RefundServiceFactory>();
services.TryAddSingleton<IScriptTagServiceFactory, ScriptTagServiceFactory>();
services.TryAddSingleton<IShippingZoneServiceFactory, ShippingZoneServiceFactory>();
services.TryAddSingleton<IShopPlanServiceFactory, ShopPlanServiceFactory>();
services.TryAddSingleton<IShopServiceFactory, ShopServiceFactory>();
services.TryAddSingleton<IShopifyPaymentsServiceFactory, ShopifyPaymentsServiceFactory>();
services.TryAddSingleton<ISmartCollectionServiceFactory, SmartCollectionServiceFactory>();
services.TryAddSingleton<IStorefrontAccessTokenServiceFactory, StorefrontAccessTokenServiceFactory>();
services.TryAddSingleton<ITenderTransactionServiceFactory, TenderTransactionServiceFactory>();
services.TryAddSingleton<IThemeServiceFactory, ThemeServiceFactory>();
services.TryAddSingleton<ITransactionServiceFactory, TransactionServiceFactory>();
services.TryAddSingleton<IUsageChargeServiceFactory, UsageChargeServiceFactory>();
services.TryAddSingleton<IUserServiceFactory, UserServiceFactory>();
services.TryAddSingleton<IWebhookServiceFactory, WebhookServiceFactory>();

return services;
}
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/AccessScopeServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface IAccessScopeServiceFactory
{
/// Creates a new instance of the <see cref="IAccessScopeService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IAccessScopeService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IAccessScopeService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IAccessScopeService Create(ShopifyApiCredentials credentials);
}
public interface IAccessScopeServiceFactory : IServiceFactory<IAccessScopeService>;

public class AccessScopeServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IAccessScopeServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/ApplicationCreditServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface IApplicationCreditServiceFactory
{
/// Creates a new instance of the <see cref="IApplicationCreditService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IApplicationCreditService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IApplicationCreditService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IApplicationCreditService Create(ShopifyApiCredentials credentials);
}
public interface IApplicationCreditServiceFactory : IServiceFactory<IApplicationCreditService>;

public class ApplicationCreditServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IApplicationCreditServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/ArticleServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface IArticleServiceFactory
{
/// Creates a new instance of the <see cref="IArticleService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IArticleService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IArticleService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IArticleService Create(ShopifyApiCredentials credentials);
}
public interface IArticleServiceFactory : IServiceFactory<IArticleService>;

public class ArticleServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IArticleServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/AssetServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface IAssetServiceFactory
{
/// Creates a new instance of the <see cref="IAssetService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IAssetService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IAssetService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IAssetService Create(ShopifyApiCredentials credentials);
}
public interface IAssetServiceFactory : IServiceFactory<IAssetService>;

public class AssetServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IAssetServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/AssignedFulfillmentOrderServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface IAssignedFulfillmentOrderServiceFactory
{
/// Creates a new instance of the <see cref="IAssignedFulfillmentOrderService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IAssignedFulfillmentOrderService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IAssignedFulfillmentOrderService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IAssignedFulfillmentOrderService Create(ShopifyApiCredentials credentials);
}
public interface IAssignedFulfillmentOrderServiceFactory : IServiceFactory<IAssignedFulfillmentOrderService>;

public class AssignedFulfillmentOrderServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IAssignedFulfillmentOrderServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/BlogServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface IBlogServiceFactory
{
/// Creates a new instance of the <see cref="IBlogService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IBlogService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IBlogService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IBlogService Create(ShopifyApiCredentials credentials);
}
public interface IBlogServiceFactory : IServiceFactory<IBlogService>;

public class BlogServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IBlogServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/CancellationRequestServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface ICancellationRequestServiceFactory
{
/// Creates a new instance of the <see cref="ICancellationRequestService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
ICancellationRequestService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="ICancellationRequestService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
ICancellationRequestService Create(ShopifyApiCredentials credentials);
}
public interface ICancellationRequestServiceFactory : IServiceFactory<ICancellationRequestService>;

public class CancellationRequestServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : ICancellationRequestServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/CarrierServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface ICarrierServiceFactory
{
/// Creates a new instance of the <see cref="ICarrierService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
ICarrierService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="ICarrierService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
ICarrierService Create(ShopifyApiCredentials credentials);
}
public interface ICarrierServiceFactory : IServiceFactory<ICarrierService>;

public class CarrierServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : ICarrierServiceFactory
{
Expand Down
13 changes: 2 additions & 11 deletions ShopifySharp/Factories/ChargeServiceFactory.cs
Expand Up @@ -7,17 +7,8 @@

namespace ShopifySharp.Factories;

public interface IChargeServiceFactory
{
/// Creates a new instance of the <see cref="IChargeService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
IChargeService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="IChargeService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
IChargeService Create(ShopifyApiCredentials credentials);
}
public interface IChargeServiceFactory : IServiceFactory<IChargeService>;


public class ChargeServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : IChargeServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/CheckoutSalesChannelServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface ICheckoutSalesChannelServiceFactory
{
/// Creates a new instance of the <see cref="ICheckoutSalesChannelService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
ICheckoutSalesChannelService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="ICheckoutSalesChannelService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
ICheckoutSalesChannelService Create(ShopifyApiCredentials credentials);
}
public interface ICheckoutSalesChannelServiceFactory : IServiceFactory<ICheckoutSalesChannelService>;

public class CheckoutSalesChannelServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : ICheckoutSalesChannelServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/CheckoutServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface ICheckoutServiceFactory
{
/// Creates a new instance of the <see cref="ICheckoutService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
ICheckoutService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="ICheckoutService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
ICheckoutService Create(ShopifyApiCredentials credentials);
}
public interface ICheckoutServiceFactory : IServiceFactory<ICheckoutService>;

public class CheckoutServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : ICheckoutServiceFactory
{
Expand Down
12 changes: 1 addition & 11 deletions ShopifySharp/Factories/CollectServiceFactory.cs
Expand Up @@ -7,17 +7,7 @@

namespace ShopifySharp.Factories;

public interface ICollectServiceFactory
{
/// Creates a new instance of the <see cref="ICollectService" /> with the given credentials.
/// <param name="shopDomain">The shop's *.myshopify.com URL.</param>
/// <param name="accessToken">An API access token for the shop.</param>
ICollectService Create(string shopDomain, string accessToken);

/// Creates a new instance of the <see cref="ICollectService" /> with the given credentials.
/// <param name="credentials">Credentials for authenticating with the Shopify API.</param>
ICollectService Create(ShopifyApiCredentials credentials);
}
public interface ICollectServiceFactory : IServiceFactory<ICollectService>;

public class CollectServiceFactory(IRequestExecutionPolicy? requestExecutionPolicy = null, IShopifyDomainUtility? shopifyDomainUtility = null) : ICollectServiceFactory
{
Expand Down

0 comments on commit b8f742f

Please sign in to comment.