是否可以创建具有通用Func
作为运行时参数的T
?
我正在使用Func
创建一些使用泛型的实例。我想做这样的事情:
var myFunc = new Func<IEnumerable<T>>(x => new List<T>());
IEnumerable<string> result = myFunc<string>();
IEnumerable<int> result2 = myFunc<int>();
IEnumerable<Bar> result3 = myFunc<Bar>();
但它显然无法编译,因为此时T
未知。下面的代码将编译,但由于我需要强类型List<T>
,因此它不适用于我的情况。
var func = new Func<IList>(() => new ArrayList());
如果Func
无法使用,Expression
或delegates
是否可以使用
有关背景信息,我可以说我将此作为工厂模式的一部分与Unity IoC一起使用。我建立在这个例子上:Unity auto-factory with params。
修改 我意识到我的问题很难被问到。对不起。我试图通过不包括背景(目的)来使问题变得简单。重点是我使用Unity作为IoC并且有一个看起来像这样的工厂:
public interface ICollectionWrapperFactory
{
ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items);
}
public class CollectionWrapperFactory :ICollectionWrapperFactory
{
private readonly IUnityContainer _container;
public CollectionWrapperFactory(IUnityContainer container)
{
_container = container;
}
public ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items)
{
ICollectionWrapper<T> collectionWrapper;
if (items == null)
{
collectionWrapper = _container.Resolve<ICollectionWrapper<T>>(new ParameterOverride("items", new T[0]));
}
else
{
collectionWrapper = _container.Resolve<ICollectionWrapper<T>>(new ParameterOverride("items", items));
}
return collectionWrapper;
}
}
正在使用IUnityContainer
来解析实例。但是我想从实现中删除对IUnityContainer
的依赖性,因为服务定位器反模式。相反,我想做这样的事情:
public class CollectionWrapperFactory :ICollectionWrapperFactory
{
private readonly Func<IEnumerable<T>, ICollectionWrapper<T>> _createFunc;
public CollectionWrapperFactory(Func<IEnumerable<T>, ICollectionWrapper<T>> createFunc)
{
_createFunc = createFunc;
}
public ICollectionWrapper<T> CreateCollection<T>(IEnumerable<T> items)
{
ICollectionWrapper<T> collectionWrapper;
if (items == null)
{
collectionWrapper = _createFunc(new T[0]);
}
else
{
collectionWrapper = _createFunc(items);
}
return collectionWrapper;
}
}
public class CollectionWrapper<TModel> : ICollectionWrapper<TModel>
{
private IEnumerable<TModel> _items;
public CollectionWrapper(IEnumerable<TModel> items)
{
_items = items;
TotalCount = items.Count();
}
public int TotalCount { get; set; }
public IEnumerable<TModel> Items
{
get { return _items; }
set { _items = value; }
}
}
在我的注册中:
container.RegisterType<ICollectionWrapperFactory, CollectionWrapperFactory>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(
new Func<IEnumerable<T>, ICollectionWrapper<T>>(
items => container.Resolve<ICollectionWrapper<T>>(new ParameterOverride("items", items)))));
container.RegisterType(typeof(ICollectionWrapper<>), typeof(CollectionWrapper<>), new TransientLifetimeManager());
这样我将从实现中删除对IUnityContainer的依赖,从而删除服务定位器反模式(我猜?)。相反,我需要注入func来创建实例,但我不知道如何使用泛型参数注入func。
正是我想要的好例子,但是有了泛型:
答案 0 :(得分:1)
您可以将其包装在方法中。
public static class MyFactories {
public static Func<IEnumerable<T>> CreateListFactory<T>() {
return () => new List<T>();
}
}
// ... somewhere else
var myFunc = MyFactories.CreateListFactory<string>();
var result = myFunc(); // it will be List<string>
修改强> 如果要声明通用字段/属性,则必须在类中指定泛型参数。
public class CollectionWrapperFactory<T> : ICollectionWrapperFactory
{
private readonly Func<IEnumerable<T>, ICollectionWrapper<T>> _createFunc;
public CollectionWrapperFactory(Func<IEnumerable<T>, ICollectionWrapper<T>> createFunc)
{
_createFunc = createFunc;
}
public ICollectionWrapper<T> CreateCollection(IEnumerable<T> items)
{
ICollectionWrapper<T> collectionWrapper;
if (items == null)
{
collectionWrapper = _createFunc(new T[0]);
}
else
{
collectionWrapper = _createFunc(items);
}
return collectionWrapper;
}
}
答案 1 :(得分:0)
您可以使用简单的方法作为工厂。
Func<IEnumerable<T>> CreateFunc<T>() {
return () => new List<T>();
}
// Usage
var func = CreateFunc<string>();
var list = func();