Castle windsor类型工厂 - 使用运行时类型作为参数解析通用服务

时间:2017-11-30 07:53:32

标签: c# generics castle-windsor

我有一个使用此方法的打字工厂:

IRepository<T> Get<T>() where T : class

和以下组件类型选择器:

public class RepositoryComponentSelector : DefaultTypedFactoryComponentSelector
    {
        protected override string GetComponentName(MethodInfo method, object[] arguments)
        {
            return ComponentNames.Repository;
        }

        protected override Type GetComponentType(MethodInfo method, object[] arguments)
        {
               return typeof(Repository<>).MakeGenericType(method.GetGenericArguments()[0]);
        }
    }

然而,我想要的是一个返回Repository的工厂实现,但只需要指定Type类型的参数,而不是编译时类型参数。

示例(无效代码) - 我希望T为提供的类型

IRepository<T> Get(Type type);

我知道这不会编译,因为方法本身必须是通用的,但我事先并不知道参数。

我想要实现的是简化这种模式:

if (documentType == SomeEnum.x)
{
    this.RepositoryFactory.Get<X>().Update(document as X);
}
else if (documentType == SomeEnum.y)
{
    this.RepositoryFactory.Get<Y>().Update(document as Y);
}
else if (documentType == SomeEnum.z)
{
    this.RepositoryFactory.Get<Z>().Update(document as Z);
}

通过基于枚举(或枚举返回类型的扩展名)解析工厂。

有没有办法通过Castle Windsor或其他任何方法实现这一目标?

1 个答案:

答案 0 :(得分:1)

我认为这更多是关于多态性和一般调度问题,而不是将其挂钩到容器中。

您可以使用双重调度方法:

public void Save(DocumentBase document)
{
    var dispatcher = new DocumentDispatcher();
    document.Accept(dispatcher);
}

public abstract class DocumentBase
{
    public abstract void Accept(IDocumentDispatcher dispatcher);
}

public class DocumentA : DocumentBase
{
    public override void Accept(IDocumentDispatcher dispatcher)
    {
        dispatcher.Dispatch(this);
    }
}

public class DocumentB : DocumentBase
{
    public override void Accept(IDocumentDispatcher dispatcher)
    {
        dispatcher.Dispatch(this);
    }
}

public interface IDocumentDispatcher
{
    void Dispatch(DocumentA document);

    void Dispatch(DocumentB document);
}

public class DocumentDispatcher : IDocumentDispatcher
{
    public void Dispatch(DocumentA document)
    {
        this.RepositoryFactory.Get<DocumentA>().Update(document);
    }

    public void Dispatch(DocumentB document)
    {
        this.RepositoryFactory.Get<DocumentB>().Update(document);
    }
}

或者您可以使用动态调度:

public void Save(DocumentBase document)
{
    var dispatcher = new DocumentDispatcher();
    dispatcher.Dispatch((dynamic)document);
}

public class DocumentDispatcher : IDocumentDispatcher
{
    public void Dispatch<T>(T document)
    {
        this.RepositoryFactory.Get<T>().Update(document);
    }
}

甚至字典发送:

public void Save(DocumentBase document)
{
    var actions = new Dictionary<Type, Action<DocumentBase>>
                      {
                          { typeof(DocumentA), d => this.RepositoryFactory.Get<DocumentA>().Update((DocumentA)d) },
                          { typeof(DocumentB), d => this.RepositoryFactory.Get<DocumentB>().Update((DocumentB)d) },
                      };

    actions[typeof(DocumentBase)](document);
}

我更喜欢第一种解决方案,因为它只是一种安全的解决方案。