C#在运行时返回泛型类型,不带类型参数
是否可以返回类型为的对象C#在运行时返回泛型类型,不带类型参数,c#,generics,return,C#,Generics,Return,是否可以返回类型为的对象 IModel< T > 我想到了一个解决办法,比如 公共IModel GetModel(类型t)和一个包装器,用于将其转换为正确的类型 我希望我没有完全错。 这是我的第一个问题。如果您的问题是如何返回IModel的实例,但您不知道编译时t是什么,只是它总是从IFactoryItem派生,那么: 如果在方法输入中不使用t,并且t是一个类,则可以使用协方差: public interface IModel<out T> where T : cla
IModel< T >
我想到了一个解决办法,比如
公共IModel GetModel(类型t)和一个包装器,用于将其转换为正确的类型
我希望我没有完全错。
这是我的第一个问题。如果您的问题是如何返回
IModel
的实例,但您不知道编译时t
是什么,只是它总是从IFactoryItem
派生,那么:
如果在方法输入中不使用t
,并且t
是一个类,则可以使用协方差:
public interface IModel<out T> where T : class
{
T Value { get; }
}
public class Model<T> : IModel<T> where T : class
{
public T Value { get; set; }
}
class Program
{
static void Main(string[] args)
{
var foo = new Model<string>()
{
Value = "hello world",
};
IModel<object> boo = foo;
Console.WriteLine(boo.Value);
}
}
如果您的问题是如何在运行时只知道类型的情况下创建
模型的实例,则其:
var someType = typeof (SomeFactoryItem);
var instance = Activator.CreateInstance(typeof (Model<>).MakeGenericType(someType));
var someType=typeof(SomeFactoryItem);
var instance=Activator.CreateInstance(typeof(Model).MakeGenericType(someType));
您仍然需要返回IModel
,或者,如果可以使用covarience,IModel
是否可以在不知道类型参数的情况下返回类型为IModel
的对象
从技术上说没有,但我认为这个问题实际上有点误解。T
的类型是知道吗,它只是泛型的——事实上,它是如此广为人知,甚至受到限制。注意其中T:IFactoryItem
,这表示任何试图执行AddModel
或GetModel
函数的东西都必须是实现IFactoryItem
接口的东西。如果您试图编写调用任一方法并向其中传递除IFactoryItem
接口实现以外的任何内容的东西,它甚至不会编译
请考虑下面的代码,变量即代码> FETCH < /COD>实际上是与添加的变量<代码>模型< /代码>相同的对象!
class Program
{
static void Main()
{
var test = new Test();
var model = new Model();
test.AddModel(model);
var fetch = test.GetModel<FactoryItem>();
Console.WriteLine(fetch == model
? "It does in fact work..."
: "Uh, that was supposed to work?");
Console.ReadLine();
}
public class Test
{
private readonly Dictionary<Type, object> _allModelsByType;
public Test()
{
_allModelsByType = new Dictionary<Type, object>();
}
public void AddModel<T>(IModel<T> model) where T : IFactoryItem
{
_allModelsByType.Add(typeof(T), model);
}
public IModel<T> GetModel<T>() where T : IFactoryItem
{
var tmpType = typeof(T);
return _allModelsByType.ContainsKey(tmpType)
? _allModelsByType[tmpType] as IModel<T>
: null;
}
}
}
internal class FactoryItem : IFactoryItem { }
internal class Model : IModel<FactoryItem>
{
public FactoryItem Value { get; set; }
}
internal interface IFactoryItem { }
internal interface IModel<T> where T : IFactoryItem
{
T Value { get; set; }
}
类程序
{
静态void Main()
{
var测试=新测试();
var模型=新模型();
测试。添加模型(模型);
var fetch=test.GetModel();
Console.WriteLine(fetch==model
“它确实起作用了……”
:“呃,那应该有用吗?”);
Console.ReadLine();
}
公开课考试
{
专用只读词典_allModelsByType;
公开考试()
{
_allModelsByType=新字典();
}
公共void AddModel(IModel模型),其中T:IFactoryItem
{
_添加(typeof(T),model);
}
公共IModel GetModel(),其中T:IFactoryItem
{
var tmpType=类型(T);
return _allModelsByType.ContainsKey(tmpType)
?_所有模型BYTYPE[tmpType]作为IModel
:null;
}
}
}
内部类FactoryItem:IFactoryItem{}
内部类模型:IModel
{
public FactoryItem值{get;set;}
}
内部接口IFactoryItem{}
内部接口IModel,其中T:IFactoryItem
{
T值{get;set;}
}
运行此程序将输出“它确实有效…”
假设字典中的值与类型键对齐,您的方法看起来非常好。有什么问题?
var someType = typeof (SomeFactoryItem);
var instance = Activator.CreateInstance(typeof (Model<>).MakeGenericType(someType));
class Program
{
static void Main()
{
var test = new Test();
var model = new Model();
test.AddModel(model);
var fetch = test.GetModel<FactoryItem>();
Console.WriteLine(fetch == model
? "It does in fact work..."
: "Uh, that was supposed to work?");
Console.ReadLine();
}
public class Test
{
private readonly Dictionary<Type, object> _allModelsByType;
public Test()
{
_allModelsByType = new Dictionary<Type, object>();
}
public void AddModel<T>(IModel<T> model) where T : IFactoryItem
{
_allModelsByType.Add(typeof(T), model);
}
public IModel<T> GetModel<T>() where T : IFactoryItem
{
var tmpType = typeof(T);
return _allModelsByType.ContainsKey(tmpType)
? _allModelsByType[tmpType] as IModel<T>
: null;
}
}
}
internal class FactoryItem : IFactoryItem { }
internal class Model : IModel<FactoryItem>
{
public FactoryItem Value { get; set; }
}
internal interface IFactoryItem { }
internal interface IModel<T> where T : IFactoryItem
{
T Value { get; set; }
}