Castle.Windsor - How to implement TypedFactoryFacility

508 Views Asked by At

Recently, I developed a component , using factory pattern. However, I did a research. on how to improve it using TypedFactoryFacility, since we are using Castle.WIndsor.

Can you please provide a simple complete example? I have read few of them but still can't really fully understand . SO far, my code looks like that :

public class DynamoStoreService : IDynamoStoreService 
{
    private IDynamoStoreFactory _dynamoStoreFactory;
    public DynamoStoreService(IDynamoStoreFactory dynamoStoreFactory)
    {
        _dynamoStoreFactory=dynamoStoreFactory;
    }

    public IDynamoStore GetProductDataDynamoStore(string storageAccount)
    {
        return _dynamoStoreFactory.Create(storageAccount);
    }
}

public class DynamoStoreFactory : IDynamoStoreFactory
{
    private IStorageAccountSelector _storageAccountSelector;

    public DynamoStoreFactory(IStorageAccountSelector storageAccountSelector)
    {
        _storageAccountSelector = storageAccountSelector;
    }

    public IDynamoStore Create(string storageAccount)
    {
        return new AzureKeyValueStore(_storageAccountSelector.GetCredentials(storageAccount).StorageAccount, "pointerfiles");
    }
}

public class StorageAccountSelector : IStorageAccountSelector
{
    private readonly IConfigurationSettings _settings;
    public StorageAccountSelector(IConfigurationSettings settings)
    {
        _settings = settings;
    }

    BlobCredentials IStorageAccountSelector.GetCredentials(string storageAccount)
    {
        return new BlobCredentials()
        {
            Container = string.Empty,
            StorageAccount = GetStorageAccount(storageAccount)
        };
    }

    private string GetStorageAccount(string storageAccount)
    {
        switch (storageAccount)
        {
            case "CustomerPolarisingCategoryBlobStorageAccountKey":
                return _settings.CustomerPolarisingCategoryBlobStorageAccount;
            case "CustomerPolarisingSegmentBlobStorageAccountKey":
                return _settings.CustomerPolarisingSegmentBlobStorageAccount;
            case "P2ProductSimilarityBlobStorageAccountKey":
                return _settings.P2ProductSimilarityBlobStorageAccount;
            case "ProductPolarisingCategoryBlobStorageAccountKey":
                return _settings.ProductPolarisingCategoryBlobStorageAccount;
            case "ProductPolarisingSegmentBlobStorageAccountKey":
                return _settings.ProductPolarisingSegmentBlobStorageAccount;
            case "SignalBlobStorageAccountKey":
                return _settings.SignalBlobStorageAccount;
        }
        return string.Empty;
    }
}

}

So basically, the IDynamostore , whenvever called, we need to be able to pass a different connection string. I have figured out the above design.. could this be improved using TypedFactoryFacility?

Thanks

1

There are 1 best solutions below

0
Marwijn On

Maybe the code below can give you an idea about how to use the TypedFactoryFacility. If you have studied it and have questions about it, please let me know.

Kind regards, Marwijn.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
using Castle.Windsor;

namespace ConsoleApplication3
{
    public class TypedFactoryComponentSelector : DefaultTypedFactoryComponentSelector
    {
        private readonly StorageAccountSelector _storageAccountSelector;

        public TypedFactoryComponentSelector(StorageAccountSelector storageAccountSelector)
        {
            _storageAccountSelector = storageAccountSelector;
        }

        protected override System.Collections.IDictionary GetArguments(MethodInfo method, object[] arguments)
        {
            var dictionary = new Dictionary<string, object>();

            dictionary.Add("mappedStorageAccount", _storageAccountSelector.GetCredentials((string)arguments[0]).StorageAccount);
            dictionary.Add("files", "pointerfiles");

            return dictionary;
        }
    }

    public interface IDynamoStore
    {
    }

    public class AzureKeyValueStore : IDynamoStore
    {
        public AzureKeyValueStore(string mappedStorageAccount, string files)
        {
            Console.WriteLine(mappedStorageAccount);
            Console.WriteLine(files);
        }
    }

    public class BlobCredentials
    {
        public string Container { get; set; }
        public string StorageAccount { get; set; }
    }


    public interface IDynamoStoreFactory
    {
        IDynamoStore Create(string storageAccount);
    }

    public class StorageAccountSelector
    {

        public BlobCredentials GetCredentials(string storageAccount)
        {
            return new BlobCredentials()
            {
                Container = string.Empty,
                StorageAccount = GetStorageAccount(storageAccount)
            };
        }

        public string GetStorageAccount(string storageAccount)
        {
            return storageAccount + "Mapped";
            return string.Empty;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var container = new WindsorContainer();
            container.AddFacility<TypedFactoryFacility>();

            container.Register(
                Component.For<IDynamoStoreFactory>().AsFactory(new TypedFactoryComponentSelector(new StorageAccountSelector())),
                Component.For<IDynamoStore>().ImplementedBy<AzureKeyValueStore>()
            );

            var factory = container.Resolve<IDynamoStoreFactory>();
            factory.Create("storageAccount");
        }
    }
}