通过反射调用泛型方法的辅助方法

时间:2019-07-10 22:02:15

标签: c# generics reflection

有人能更好地做到以下几点吗?

typeof(Service).GetMethod("UpdateData")
    .MakeGenericMethod(dataType)
    .Invoke(_myService, new object[]{ editData, metaData });

我想做类似的事情:

_myService.UpdateData<dataType>(editData, metaData);

但是泛型的<>访问器将不接受Type对象。我正在寻找一个帮助程序,实用程序,访问器或其他方法,以使那些具有反射功能的通用方法调用不那么麻烦或至少集中化。

更具体的示例

public class UserService : IUserService
{
  async Task<User> UpdateUser<T>(User user, JsonPatchDocument<T> patch){ //do code }
}

Type dtoType = MagicService.getDynamicDtoType();
Type patchType = typeof(JsonPatchDocument<>).MakeGenericType(dtoType);
dynamic patchDoc = _mapper.Map(patch, typeof(JsonPatchDocument<User>), patchType);
User updateUser = await (Task<User>)typeof(UserService).GetMethod("UpdateUser").MakeGenericMethod(dtoType).Invoke(_userService, new object[]{user, patchDoc})

这实际上有两个问题。第一,dynamic patchDoc不是UpdateUser中使用的正确类型,我在Stackoverflow中有一个单独的问题(但是您可以在此处使用鸭子类型),并且该泛型的混乱调用具有反射的方法调用。我正在尝试解决这两个问题,但是对于这个问题,我想清理电话。如果您对另一部分有想法,那实际上是一个单独的问题: Declaring a type in C# with a Type instance

1 个答案:

答案 0 :(得分:1)

此答案不使用反射,但是可以使您的代码在某些情况下更易于使用。

我们可以有一个像这样的课程:

public class MyService
{
    public void UpdateData<T>(Something data, Something otherData)
    {
        // do stuff
    }
}

稍后,我们发现必须使用Type变量而不是通用参数来调用它,这可能意味着使用反射。有时,将非泛型重载添加到原始类中并从泛型方法中调用它会更容易:

public class MyService
{
    public void UpdateData(Type dataType, Something data, Something otherData)
    {
        // do stuff
    }

    public void UpdateData<T>(Something data, Something otherData)
    {
        UpdateData(typeof(T), data, otherData);
    }
}

我们失去了像普通方法那样容易对Type自变量施加约束的能力。我们可以根据需要添加验证。

这使您尽可能接近要编写的代码:

_myService.UpdateData(dataType, editData, metaData);

这是假设您发现自己仍然仍然需要通用方法。如果您添加非泛型重载,并且发现不再调用泛型重载,则可以将其删除。

此操作比反射功能的显着优势是您可以识别代码的调用位置。仅使用反射调用的方法将显示为未使用。