How do you get the type of generic argument from t

2019-05-28 23:48发布

We are supposed to instantiate our entities through a factory since they are set up differently on the client and server. I want to make sure this is the case but cant quite get it to work.

public interface IEntityFactory
{
    TEntity Create<TEntity>() where TEntity : new();
}

public abstract class Entity
{
    protected Entity()
    {
        VerifyEntityIsCreatedThroughFactory();
    }

    [Conditional("DEBUG")]
    private void VerifyEntityIsCreatedThroughFactory()
    {
        foreach (var methodBase in new StackTrace().GetFrames().Select(x => x.GetMethod()))
        {
            if (!typeof(IEntityFactory).IsAssignableFrom(methodBase.DeclaringType)
                || methodBase.Name != "Create")
                continue;

            // The generic type is TEnitiy but I want the provided type!
            if (methodBase.GetGenericArguments()[0] != GetType())
                Debug.Fail(string.Format("Use factory when creating {0}.", GetType().Name));
        }
    }
}

3条回答
聊天终结者
2楼-- · 2019-05-29 00:16

Is possible to address this structurally instead of at runtime? Can you segregate your entities and the factory in a different assembly, then give the entity constructors internal scoping so that only the factory is able to invoke them?

查看更多
贼婆χ
3楼-- · 2019-05-29 00:19

Thanks for your replies. Setting the constructor to internal is not a possibility as we have multiple assemblies containing entities. Right now I'm leaning towards creating a class where the factory registers the type to create and the constructor checks against the registered type, it's not the solution I would prefer but it will do for now.

查看更多
虎瘦雄心在
4楼-- · 2019-05-29 00:37

The problem is that the factory method type is resolved at runtime, so the method is considered an "open" one. In that case, the generic argument type will return TEntity, as you are seeing.

Unfortunately, (unless I am missing something), the only way to get what type of TEntity is if a closed method is first created using MethodInfo.MakeGenericMethod and then executed, which is of course not likely to be done by your callers.

See this MSDN page for additional details.

查看更多
登录 后发表回答