简体   繁体   中英

How to use a variable as a Type?

I have an object that is passed to me as ISomething. I need to serialize the object however my serilizer expects a type parameter of a concrete type ie:

string xml = Utilities.Serialize<ConcreteType>(myObject);

Basically I want to to the same thing as this guy: Creating a generic object based on a Type variable

however I dont want to create a new instance of an object I want to use the resulting type as a parameter to my generic class.

So my question in a nutshell is how do I create some variable that represents the concrete type of some object that I can use with a generic class like this:

string xml = Utilities.Serialize<ConcreteType>(myObject);

where ConcreteType is what I need to create.

So let's say you've got something like:

public static class Util
{
    public static T Foo<T>(object obj)
    {
         // Do actual stuff here
         return default(T);
    }
}

Normally, the compiler would wire up any usage of this method, swapping in the appropriate generic variant based on what you passed it. We no longer can rely on the compiler if you have a variable containing the Type - but we can ask the class to give us the variant we want:

public void DoFooWith(object blob)
{
    // Get the containing class
    var utilType = typeof(Util);
    // Get the method we want to invoke
    var baseMethod = utilType.GetMethod("Foo", new Type[]{typeof(object)});
    // Get a "type-specific" variant
    var typedForBlob = baseMethod.MakeGenericMethod(blob.GetType());
    // And invoke it
    var res = typedForBlob.Invoke(null, new[]{blob});
}

If you absolutely need to get the type of the actual object you can use GetType(). The problem is, you will have to call all your functions using reflection because as far as I know there no easy way to call them with a variable with the type.

You can not guarantee that all ISomething 's are ConcreteType 's but you can cast them and pass on the ones that work.

string CastAndSerialize(ISomething somthing)
{
    //castSomthing will be null if ISomthing was not a ConcreteType.    
    ConcreteType castSomthing = somthing as ConcreteType; 

    if(castSomthing != null)
    {
       return Utilities.Serialize<ConcreteType>(castSomthing );
    }
    else
    {
        return null; //Or whatever you want to use to represent that the cast failed.
    }
}

Here is a more generic version, this will work with anything that is a class .

string CastAndSerialize<T>(ISomething somthing) where T : class
{ 
    T castSomthing = somthing as T; 

    if(castSomthing != null)
    {
       return Utilities.Serialize<T>(castSomthing );
    }
    else
    {
        return null;
    }
}

Could be a case for another form of generic method. If you own Utilities.Serialize(...) and can generate a new overload, take a look at:

http://msdn.microsoft.com/en-US/library/twcad0zb(v=VS.80).aspx

For example:

string Utilities.Serialize<T>(T object) 
    where T : ConcreteType

Upon further reflection (pun intended) could the following be what you are looking for?

Calling a generic method with a dynamic type

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM