C# Castle windsor类型化工厂-使用运行时类型作为参数解析泛型服务
我有一个使用此方法的类型化工厂:C# Castle windsor类型化工厂-使用运行时类型作为参数解析泛型服务,c#,generics,castle-windsor,C#,Generics,Castle Windsor,我有一个使用此方法的类型化工厂: IRepository<T> Get<T>() where T : class IRepository Get()其中T:class 和以下组件类型选择器: public class RepositoryComponentSelector : DefaultTypedFactoryComponentSelector { protected override string GetComponentName(Met
IRepository<T> Get<T>() where T : class
IRepository Get()其中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]);
}
}
公共类RepositoryComponentSelector:DefaultTypedFactoryComponentSelector
{
受保护的重写字符串GetComponentName(MethodInfo方法,对象[]参数)
{
返回ComponentNames.Repository;
}
受保护的重写类型GetComponentType(MethodInfo方法,对象[]参数)
{
返回typeof(Repository).MakeGenericType(方法.GetGenericArguments()[0]);
}
}
但是,我希望有一个返回存储库的工厂实现,但只需要指定类型为的参数,而不是编译时类型的参数
示例(无效代码)-我希望T是提供的类型
IRepository<T> Get(Type type);
i存储获取(类型);
我知道这不会编译,因为方法本身必须是泛型的,但我事先不知道参数
我试图实现的是简化此模式:
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);
}
if(documentType==SomeEnum.x)
{
this.RepositoryFactory.Get().Update(文档为X);
}
else if(documentType==SomeEnum.y)
{
this.RepositoryFactory.Get().Update(文档为Y);
}
else if(documentType==SomeEnum.z)
{
this.RepositoryFactory.Get().Update(文档为Z);
}
通过基于枚举(或该枚举返回类型的扩展)解析工厂
有没有办法通过Castle Windsor或其他我可以采取的方法来实现这一点?我认为这更多是关于多态性和一般调度问题,而不是将其挂接到容器中 您可以使用双重分派方法:
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);
}
}
公共作废保存(DocumentBase文档)
{
var dispatcher=newdocumentdispatcher();
文件接收(调度员);
}
公共抽象类文档库
{
公共摘要无效接受(IDocumentDispatcher);
}
公共类文档:文档库
{
公共覆盖无效接受(IDocumentDispatcher)
{
调度员。调度(本);
}
}
公共类DocumentB:DocumentBase
{
公共覆盖无效接受(IDocumentDispatcher)
{
调度员。调度(本);
}
}
公共接口IDocumentDispatcher
{
无效派送(文件);
无效派送(文件B文件);
}
公共类DocumentDispatcher:IDocumentDispatcher
{
公共无效调度(文件文件)
{
this.RepositoryFactory.Get().Update(文档);
}
公共无效调度(文件B文件)
{
this.RepositoryFactory.Get().Update(文档);
}
}
或者,您可以使用动态分派:
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);
}
公共作废保存(DocumentBase文档)
{
var dispatcher=newdocumentdispatcher();
调度员.调度((动态)文件);
}
公共类DocumentDispatcher:IDocumentDispatcher
{
公共无效调度(T文件)
{
this.RepositoryFactory.Get().Update(文档);
}
}
甚至字典发送:
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);
}
公共作废保存(DocumentBase文档)
{
var actions=新字典
{
{typeof(DocumentA),d=>this.RepositoryFactory.Get().Update((DocumentA)d)},
{typeof(DocumentB),d=>this.RepositoryFactory.Get().Update((DocumentB)d)},
};
行动[类型(文档库)](文档);
}
我更喜欢第一种解决方案,因为它只是一种类型安全的解决方案。我认为双调度方法在这种情况下不可用。我没有继承层次结构,只是根据一个枚举来决定。我也不喜欢所有额外的样板代码。字典分派可以工作,但仅适用于操作方法。如果它是一个Func,那么我的位置和以前一样——我必须让方法返回对象,然后将其强制转换,对吗?后续评论:我误解了双重分派方法。这对我有用。然而,我仍然不喜欢所有额外的样板。此外,在我看来,这样我使我的POCO对象具有依赖性(仅通过一个参数,但仍然)。@FreHu,如果第一个解决方案有效,那么第二个解决方案也会有效……代码更少,无需在POCO对象上添加任何方法,但类型安全性更低。如果你不喜欢额外的编码,你无论如何都会有问题。我觉得创建一些Castle boiler plate代码,比如你的
RepositoryComponentSelector
更糟糕。关于您的POCO问题,类将只依赖于您的接口,而不是具体的接口。没有实际理由认为这会成为一个问题。