How to instantiate an interface, with a generic parameter - c#

I have some classes that implement the interface below:
ISearchBase<T>
But I don't know which class will be instantiated, so I let "the user decide", like the example below:
var objectResponse = Activator.CreateInstance(Type.GetType(ResponseNamespace));
The problem is:
Each those classes has a return and I'm trying to use like this:
var object = (ISearchBase<objectResponse >)
Activator.CreateInstance(Type.GetType(Namespace));
But the compiler won't let me do this... What can I do?
The error is:
The type or namespace name 'objectResponse' could not be found.

When you do var object = (ISearchBase<X>)... you must know the type X at compile time. The var keyword is just short-hand for the compiler to infer the type. So, you cannot use a run-time type to resolve for X.
You haven't shown what you what to do with the object after you've created it. It is certainly possible to call a generic method using reflection to allow you to type-safe code, but I can't tell if that will be useful to you or not without seeing more code.

Related

C# Getting Type out of a string variable and using it in generic method

I want to be able to get the actual Type of a string value I receive by some means (i.e from database) so I can use that Type in generic method like DoSomething<Type>().
In my project, I have classes Plane, and Car located in MyCompany.MySolution.Vehicle namespace like so
- MyCompany.MySolution.Vehicle
|+Interfaces
|-Implementations
|-Car
|-Plane
I receive type of the vehicle as a string. So, I get string "Car" which means, I need to get Type Car so I can use that type in a generic method to register it like so:
MyFactory.Register<Car>(carId)
So, MyFactory is static class calling Register() method.
Similarly, I receive string "Plane" which means, I need to get Type Plane so I can use that type in the generic method above to register a Plane.
I tried using something like
MyFactory.Register<Type.GetType("MyCompany.MySolution.Vehicle.Implementations.Car")>(carId)
,but that does not work.
If you want to invoke a Generic Method with a Type parameter generate at Runtime, you could do something like this:
var vehicleString = "Car";
// use the fully-qualified name of the type here
// (assuming Car is in the same assembly as this code,
// if not add a ", TargetAssemblyName" to the end of the string)
var vehicleType =
Type.GetType($"MyCompany.MySolution.Vehicle.Implementations.{vehicleString}");
// assuming MyFactory is the name of the class
// containing the Register<T>-Method
typeof(MyFactory).GetMethod("Register")
.MakeGenericMethod(vehicleType)
.Invoke(this);
Working Example
Just as a note:
This is not how generics are supposed to be used. I'm just pointing out the possibility, not giving you an ideal answer to the problem you're proposing. Maybe you should rethink some of your architectural design choices!
If Register<T> does something like this
void Register<T>(int id)
{
_dictionary.Add(typeof(T), ...);
}
Create a non generic overload
void Register(Type t, int id)
{
_dictionary.Add(t, ...);
}
This new overload is not type safe, but creating a type out of a string isn't anyway.
The purpose of generics is to gain variability (not to be confused with dynamic behavior!) while keeping type safety. But when types are determined at runtime, type safety is not given and generics are more of a hindrance than useful.
Note that type safety is ensured by the compiler, which does of course not work at runtime.
You can use a dictionary which holds all your types with strings keys:
var d = new Dictionary<String,Type>();
d.Add("Car",typeof(Car));
d.Add("Plane",typeof(Plane));
Then if you get the string "Car" from the database you can get the type like this:
var myType = d["Car"];
Then use myType as the real Type.

Create Generic List<Type> from PropertyInfo

In one of my classes I have the following property:
public List<ClassP> MyPlanes { get; set; }
In another method I have a the propertyInfo of the property above (the function self does not know where the propertyinfo comes from). Right now i'm trying to create a list of classP when i only have the propertyInfo of MyPlanes. So far my attempts seem to be in vain, this is howfar i got sofar:
variable prop is the PropertyInfo of MyPlanes
public void GenerateList(PropertyInfo prop)
{
if (prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericArguments().Length > 0)
{
List<prop.PropertyType.GetGenericArguments().First()> myValueList =
new List<prop.PropertyType.GetGenericArguments().First()>();
}
}
The creating of the list (with the code above) gives the following error Using the generic type 'System.Collections.Generic.List<T>' requires 1 type arguments
Any help would be greatly appreciated
Note: I want the list creating in a syntax (or a syntax similar) as visible above. I want to keep my code as generic as possible
To make a generic class when you have the type, you can't use the brackets <> because you don't know the type at compile time. You need to do something like this:
var baseType = typeof(List<>);
var genericType = baseType.MakeGenericType(prop.PropertyType.GetGenericArguments().First());
Now you have the correct type and you can create it like so:
IList myList = (IList)Activator.CreateInstance(genericType);
Edit: although as Selman22 says above, you already have the PropertyType, so you don't need to get the generic type unless you are trying to make a different generic class with the same generic argument (say you have a List<T> and need to make a Dictionary<Type,T> or something). So I'll leave my answer in case you encounter that situation.
Unfortunutely, it does not work like that.You need to use Reflection to create a new instance as well:
var list = (List<ClassP>)Activator.CreateInstance(prop.PropertyType);
CreateInstance method returns object. If you don't know the type at compile time, there is no way to cast it. Best thing you can to would be using dynamic.And that way you can access any members without any compile time error, but clearly it's not safe.
You should probably reconsider whether you really need to use Reflection here.If your problem can be solved without using Reflection then you should go with that way.

Why does my non-dynamic class method return dynamic

The following code results in the C# compiler returning a dynamic type, but that class and the GetUserProfileAsync method are normal, 'concrete' code.
var profile = await this.UserProfileRepository.GetUserProfileAsync(this.ViewModel[ViewModelKeys.UserGivenName]);
Intellisense on the profile variable is absent, instead the editor/compiler says:
This operation will be resolved at runtime.
What's going on?
Check the type of the parameter being passed into the GetUserProfileAsync method, its probably dynamic.
The compiler cannot thus know the type and resolve the method/callsite on the UserProfileRepository class.
To fix the issue, cast the value coming from this.ViewModel to the type you expect.
var profile = await this.UserProfileRepository.GetUserProfileAsync((string)this.ViewModel[ViewModelKeys.UserGivenName]);
Now the compiler can work it all out.

Why can't I use a "Type" to create a new variable in C#?

int number = 5;
Type dynamicType = number.GetType(); // dynamic type is "int"
dynamicType x = (number as dynamicType);
How would you expect the compiler to treat the variable x later in the code? It wouldn't know anything about it... so it couldn't resolve any method calls etc.
Basically what you're after is dynamic typing which is supported in C# 4 with the "dynamic" pseudo-type:
int number = 5;
dynamic d = number;
// Calls to d are resolved at execution time, so this compiles:
d.ThisWillThrowAtExecutionTime();
Type is an object that represents information about a type. It's not a designator for a variable saying it is of that type.
SomeObject myObject = new SomeObject();
Type t = myObject.GetType();
SomeObject myOtherObject = (SomeObject)Activator.CreateInstance(t);
The ability to do this goes all the way back to .Net v1.0. No need for fancy dynamic typing or anything like that.
Constructing objects with more complex constructors takes a bit more work, but it's the same idea.
You can, just not directly. You can use reflection. Basically you get the fully qualified name of the type (from the Type object) and then call CreateInstance method from an assembly object that contains that type. It should be quite simple to get the assembly reference of the current instance...
I think the Assembly.GetExecutingAssembly() method will do it.
I've written a little about this quite some time ago in a post at: http://frater.wordpress.com/2007/06/24/instantiating-classes-through-reflection-using-c-dynamic-object-creation/
That might help you out some more, though the focus was also on compiling of c# code from within a c# program, to allow for the use of C# as a scripting language, so some of the details might not be completely relevant.
Hope that helps!
Because it wouldn't make any sense.
What would you do next?
The purpose of a cast is to assign the casted object to a variable of the type that you casted it to. In this case, you wouldn't be able to do that, since a field must have a static type at compile time.
What are you trying to do?
dynamicType is an object of type "Type" that holds the Type meta-data information of type "int" hence dynamicType is and instance or object and not a qualified type so you cannot perform instantiation on that.
So, AFAIK you can't use the Type to instantiate 'basic' data types such as int.
You could use it to create objects though:
Object x=Activator.CreateInstance(dynamicType)
The issue is, if you want to call methods or access fields on a dynamic type, you have to use reflection. See the Type class documentation for instructions.

How do I creating Generic object from dynamically loaded Type?

I'm getting a Type using Assembly class as follows:
var asm = Assembly.GetAssembly(typeof(MyAssembly));
var t=asm.GetType("FULLY QUALIFIED CLASS NAME", true, true);
Then I create object from this type:
var obj = Activator.CreateObject(t, new []{ params });
Now I want to convert or cast this object to a Generic object (actually SubSonic Active Record Object).
var record = (ActiveRecord<PUT SOMEHOW TYPE t HERE>)obj;
How can I accomplish this?
The point of static typing is that you know the type at compile time.
What do you expect the type of the record variable to be? The compiler needs to know - it can't wait until execution time.
What do you want to do with record anyway? If the real goal is to create an ActiveRecord<T> object but you don't need to know the T for any other operations, then you'll need to use reflection with Type.MakeGenericType or MethodInfo.MakeGenericMethod depending on the ActiveRecord API (which I'm not familiar with)... but you're not going to be able to use the result in a statically typed way (that depends on T) in the lines of code which follow.
Does ActiveRecord<T> implement a nongeneric interface? If so, that's what you'd usually use after constructing the relevant instance.
If you can provide a link to ActiveRecord<T> documentation to show how to construct an instance, I'm happy to write the reflection code for you...
your class must inherit ActiveRecord or by itself be ActiveRecord .
you are trying to cast a type into another object receving the fomer as varible:
Cat c = new Cat();
List<Cat> l = (List<Cat>) c; // error.

Categories

Resources