문제

Can I use a type from reflection as a type parameter? E.g. I want to pick a persister based on a passed object:

IPersister GetPersisterFor(IEntity entity)
{
    return GetPersisterFor<entity.GetType()>(); // <-- this cannot be compiled
}

IPersister GetPersisterFor<TEntity>() where TEntity : IEntity
{
    //some logic to get persister...
}
도움이 되었습니까?

해결책

Only via reflection; you would need to use GetMethod to get the MethodInfo for the generic method, then call MakeGenericMethod(entity.GetType()).Invoke(this, null); on that.

However, easier is to cheat via dynamic:

IPersister Evil<T>(T obj) where T : IEntity {
    return GetPersisterFor<T>();
}

And make the first method just:

return Evil((dynamic)entity);

This is then a dynamic expression which will detect the correct T to use (to call Evil-of-T) for you.

Note: the only reason you need an extra method is to make sure it doesn't resolve back to itself recursively, since the names are the same.

다른 팁

Yes, you need to get the generic method definition. After that you can use MethodInfo.MakeGenericMethod to construct the generic method.

So something like:

MethodInfo genericMethodDefinition = GetType()
    .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
    .Where(method => method.IsGenericMethod && method.Name == "GetPersisterFor")
    .First();

// OR

MethodInfo genericMethodDefinition = GetType().GetMethod("GetPersisterFor",
    BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);

// THEN

MethodInfo genericMethod = genericMethodDefinition.MakeGenericMethod(entity.GetType());
genericMethod.Invoke(this, null);

Because both generic and non generic methods have same name, you have to iterate over all methods of class to find proper one, and then invoke it:

public IPersister GetPersisterFor(IEntity entity)
{       
    MethodInfo getPersisterForGenericMethod = 
                    GetType().GetMethods()
                        // iterate over all methods to find proper generic implementation
                        .Single(methodInfo => methodInfo.Name == "GetPersisterFor" && methodInfo.IsGenericMethod)
                        // supply it with generic type parameter
                        .MakeGenericMethod(entity.GetType());

    // invoke it
    return getPersisterForGenericMethod.Invoke(this, null) as IPersister;
}

public IPersister GetPersisterFor<TEntity>() where TEntity : IEntity
{
    return null;
}

ps: full source code available at gist.github

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top