Reputation: 129
Is it possible to return an object of type
IModel< T >
without knowing the type parameter?
the objects are stored in a dictionary, with Type as the key and an object with IModel
(base interface to IModel<T>
) implemented as a value.
The interface IModel<T>
inherits from IModel
, but to do the full action I need an object of IModel<T>
. T
needs to have the interface IFactoryItem
.
but first the code:
public IModel<T> GetModel<T>() where T : IFactoryItem
{
Type tmpType = typeof(T);
if (!_allModelsByType.ContainsKey(tmpType))
return null;
return (IModel<T>)_allModelsByType[tmpType];
}
i thought of a solution like
public IModel GetModel(Type t) and a wrapper to cast it to the right type.
I hope that i am not totally wrong. this is my first question.
Upvotes: 3
Views: 4134
Reputation: 26398
If your question is how to return an instance of IModel<T>
but you don't know what T
is at compile time, only that it is always derived from IFactoryItem
then:
If you don't use T
in a method input, and T
is a class you can use covariance:
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);
}
}
That way you can pass around IModel<IFactoryItem>
rather than IModel<T>
If you need value types though, or you can't use covariance then ideally you'd have (as you suggest) a second non-generic interface IModel
that exposes any values as object
public interface IModel
{
object Value { get; }
}
public class Model<T> : IModel, IModel<T>
{
public T Value { get; set; }
object IModel.Value => Value;
}
If your question is how to make an instance of Model<T>
when you only know the type at run-time then its:
var someType = typeof (SomeFactoryItem);
var instance = Activator.CreateInstance(typeof (Model<>).MakeGenericType(someType));
you will still need to either return IModel
or, if you can use covarience, IModel<IFactoryItem>
Upvotes: 2
Reputation: 24525
Is it possible to return an object of type
IModel<T>
without knowing the type parameter?
Technically no, but I think this was actually asked with a slight misunderstanding. The type of T
is know, it is just generic -- in fact it is so well known that it is even constrained. Note the where T : IFactoryItem
, this indicates that anything that attempts to execute either the AddModel
or GetModel
functions must be something that implements the IFactoryItem
interface. If you trying writing something that calls either methods and passes into it anything other than an implementation of the IFactoryItem
interface, it won't even compile.
Please consider the code below, the variable namely fetch
is actually the same object as the variable model
that was added!
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; }
}
Running this program will output "It does in fact work..."
<iframe width="100%" height="750" src="https://dotnetfiddle.net/Widget/J26ETn" frameborder="0"></iframe>
Upvotes: 0