Helper method for calling generic methods with reflection - c#

Does anyone have a better way to do the following:
typeof(Service).GetMethod("UpdateData")
.MakeGenericMethod(dataType)
.Invoke(_myService, new object[]{ editData, metaData });
I'd love to do something like:
_myService.UpdateData<dataType>(editData, metaData);
But the <> accessor for generics will not take Type objects. I'm looking for a helper, utility, accessor, or something to make those generic method calls with reflection less cumbersome or at least centralized.
More Specific Example
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})
This actually ends up with two issues. One, the dynamic patchDoc isn't the right type to be used in UpdateUser, which I have a separate question in Stackoverflow about (but you can use duck typing here), and the messy calling of that generic method call with reflection. I'm trying to solve both, but for this question I want to clean up the call. If you have ideas on the other piece, which is really a separate issue:
Declaring a type in C# with a Type instance

This answer does not use reflection, but may make your code easier to work with in some circumstances.
We could have a class like this:
public class MyService
{
public void UpdateData<T>(Something data, Something otherData)
{
// do stuff
}
}
Later we find that we have to call it using a Type variable instead of a generic argument, which could mean using reflection. Sometimes it's easier to add a non-generic overload to the original class, and call it from the generic method:
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);
}
}
We lose the ability to easily impose constraints on the Type argument like we could with the generic method. We can add validation if we need it.
That gets you as close as possible to the code you're trying to write:
_myService.UpdateData(dataType, editData, metaData);
That's assuming that you find yourself still needing the generic methods at all. If you add non-generic overloads and discover that you're not calling the generic ones anymore, you can just delete them.
A significant benefit of this over reflection is that you can identify where your code is called. A method that's only called using reflection will appear unused.

Related

C# Put Static Class Inside Dictionary

I was unclear in an earlier question I ask so I will try to be more explicit.
Is there a way to put a static class inside of a dictionary so that its functions can be called? If this is not possible, what is the best alternative that doesn't involve using instances that you can suggest?
Here is how I would like to use it:
static class MyStatic : IInterface
{
static void Do(){}
}
static class MyStatic2 : IInterface
{
static void Do(){}
}
class StaticMap
{
static Dictionary<Type,IInterface.class> dictionary = new Dictionary<Type,IInterface.class>
{
{Type.1, MyStatic}
{Type.2, MyStatic2}
};
}
// Client Code
class ClientCode
{
void Start()
{
StaticMap.dictionary[Type.1].Do();
}
}
There are some fundamental reasons why you can't do that directly:
Static method calls are bound at compile-time
Static calls are not inherited - they are tied to the class that defines them
There is no implicit base type (and therefore no polymorphism) between static methods, even if the name, inputs, and outputs are all the same
Since your signature is the same for every static method, you could store a Action in the dictionary instead:
static Dictionary<Type,Action> dictionary = new Dictionary<Type,Action>
{
{Type.1, MyStatic.Do}
{Type.2, MyStatic2.Do}
};
then you can call the Action directly:
void Start()
{
StaticMap.dictionary[Type.1]();
}
It's slightly repetetive because you have to specify the method name in the dictionary as well, but it's type safe.
A key question is whether you want to call a single method on each type or whether you need to call multiple methods belonging to each type.
If it's just a single method, then what D Stanley suggested is the answer. If you store a number of Actions, each representing a method with the same signature on a different static class, then you're accomplishing what you said.
However that raises a question - why the constraint that each method must belong to a separate static class? This approach would work just as well if some or all of the methods belonged to the same class.
If you need to call more than one method from each class then an Action no longer works. You'd have to store collections of Action, which a) means class instances, and b) is a lot more complicated than just using interfaces and class instances.
One way to manage instances is by using a dependency injection container to create class instances for you. Using that approach, you can create non-static classes without having to go through the hassle of explicitly making them singletons. But you can tell the container to only produce one of each and reuse it. For example, using Castle Windsor:
container.Register(Component.For<ISomeInterface,SomeClass>));
Now every time the container is asked to provide an instance of ISomeInterface it will always provide the same instance of SomeClass.
Because the dependency you're looking for varies by type (Dictionary<Type, Something>) it sounds like what you're looking for might be related to generics. But it would be necessary to take a step back from the smaller problem and understand a slightly larger picture of what you're trying to accomplish.
Instead of having the entire class as static, create a Singleton instance.
public class Foo
{
public static Foo _Foo;
public Foo()
{
_Foo = this;
}
}
Then you may add it to your list, and also inherit from Interfaces, etc.

Accessing nested generic type parameters

Supposed I have some code like so:
// This represents some query that will return type T when executed.
public interface IQuery<T> { }
// An example query that returns bool
public class MyQuery : IQuery<bool> { }
// A separate class that's actually responsible for executing the queries.
public class Executor {
public T Execute<T>(IQuery<T> query)
}
// Usage
executor.Execute(new MyQuery()) // => true/false
No problems so far. But say I want to change my executor class such that it's responsible for instantiation of queries. Ideally I'd like usage to be something like:
// Usage
executor.Execute<MyQuery>() // => true/false
However, I can't seem to find a way to model this method signature. The closest I can get is:
public T Execute<TQuery, T>() where TQuery : IQuery<T>
The problem with this signature is that it requires all of the type parameters to be explicitly specified. There is no way for T to be inferred from TQuery since the generic type constraints are not considered when inferring type parameters.
So far the only workaround I've found is to set up a dummy argument to help with inference from the formal parameters. Basically going back to the original example but instead of passing an actual instance using new MyQuery() I can pass something like default(MyQuery). This is clunky though and the makes the API not at all obvious.
Is there some workaround that I'm missing?

Mocking Generic Method with NSubstitute

I have an interface with a number of generic methods. These methods perform operations based on the type of data that is passed in. How do I mock this with NSubstitute? At the moment, I had to resort to using a concrete class instead of a mock since I cannot handle all possible types that the method will be called with.
public interface IInstanceSource
{
bool CanCreate<T>();
T Create<T>();
void Register<T>(Func<T> creator);
}
public static IInstanceSource GetInstanceSource()
{
var _data = new Dictionary<Type, Func<object>>();
var a = Substitute.For<IInstanceSource>();
//code below fails since T is not defined. How do I make the code below accept any type?
a.WhenForAnyArgs(x=>x.Register(Arg.Any<Func<T>>)).Do(x=> { /* todo */});
a.CanCreate<T>().Returns(x => _data[typeof (T)]);
return a;
}
thanks.
NSubstitute doesn't support setting up multiple instances of a generic method automatically.
The way we'd normally see IInstanceSource used in a test is to configure it for a specific bit of code under test, so T would be known. If a single fixture needed to work for a few different Ts, we could make configuration simpler by having a helper method like ConfigureInstanceSource<T>() which would do the configurations steps for a specific T.
In your case though it seems like you want a fixed behaviour for all fake instances of IInstanceSource, in which case I believe you are going the right way about it by hand-coding your own test double.

Is it possible to constrain a C# generic method type parameter as "assignable from" the containing class' type parameter?

I suspect the answer is no, but I want to know if it is possible to do something like this:
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>()
// This doesn't compile.
where TSomeClass : TSomeInterface
{
//...
}
}
What I mean to indicate in the above (non-working) example is to constrain TSomeInterface such that it can be any base class, implemented interface, or (if you really want to get fancy) implicit conversion of MyGenericClass.
NOTE:
I suspect that the reason why this was never implemented in C# is that generic constraints are not really meant to be code contracts, which is how I am trying to use them here. I really don't care what type TSomeInterface is, so long as it is implemented by TSomeClass.
So far, I have hacked this together:
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TIntermediateType, TSomeInterface>()
where TIntermediateType : TSomeClass, TSomeInterface
{
//...
}
}
This more or less enforces the constraint that I want (that TSomeClass must inherit from, or in the case of an interface, implement, TSomeInterface), but calling it is very clumsy, because I have to specify TIntermediateType (even though I really want it to evaluate against TSomeClass):
var myGenericInstance = new MyGenericClass<TSomeClass>();
myGenericInstance.MyGenericMethod(TSomeClass, TSomeInterface);
Additionally, the above hack is broken because a caller could in theory specify a subclass of TSomeClass as the first type parameter, where only the subclass implements TSomeInterface.
The reason that I want to do this is that I am writing a fluent factory pattern for a WCF service, and I would like to prevent the caller (at compile time) from trying to create an endpoint with a contract that the service class doesn't implement. I can obviously check this at runtime (WCF in fact does this for me), but I am a big fan of compile-time checking.
Is there a better/more elegant way to achieve what I am after here?
The way I was able to wrap my head around the reason why this doesn't compile is the following:
Consider this program compiles:
class Program {
class Class1 { }
class Class2 { }
public class MyGenericClass<TSomeClass> {
public void MyGenericMethod<TSomeInterface>() where TSomeClass : TSomeInterface {
}
}
static void Main(string[] args) {
var inst = new MyGenericClass<Class1>();
}
}
Everything is good. The compiler is happy. Now consider I change the Main method:
static void Main(string[] args) {
var inst = new MyGenericClass<Class1>();
inst.MyGenericMethod<Class2>();
}
The compiler will complain that Class1 does not implement Class2. But which line is wrong? The constraint is on the call to MyGenericMethod, but the offending line of code is the creation of MyGenericClass.
In other words, which one gets the red squiggly line?
As discussed in this linked question, you can't use a type parameter that isn't from the current declaration, on the left side of a where clause.
So as suggested by w0lf in that other question, what you can do is provide both types in your interface (rather than method) declaration:
public class MyGenericClass<TSomeClass, TSomeInterface> {
where TSomeClass : TSomeInterface
public void MyGenericMethod() // not so generic anymore :(
{
//...
}
}
That, however, greatly limits your MyGenericMethod and forces your class to declare before-hand what base interface you with to allow.
So another option is to use a static method with more type parameters:
public class MyGenericClass<TSomeClass> {
public static void MyGenericMethod<TSomeClass, TSomeInterface>
(MyGenericClass<TSomeClass> that)
where TSomeClass : TSomeInterface
{
// use "that" instead of this
}
}
Possibly you could make it an extension method to make it appear to the user like an actual method.
Neither of these is exactly what you wanted, but probably better than the intermediate type solution.
As for the reason for why not?, my guess is that it would complicate the compiler without adding enough value. Here's a discussion by Angelika Langer of the same subject but about Java. Although there are significant differences between C# and Java, I think her conclusion might apply here as well:
The bottom line is that the usefulness of lower bounds on type
parameters is somewhat debatable. They would be confusing and perhaps
even misleading when used as type parameters of a generic class. On
the other hand, generic methods would occasionally profit from a type
parameter with a lower bound. For methods, a work-around for the
lack of a lower bound type parameter can often be found. Such a
work-around typically involves a static generic method or a lower
bound wildcard.
She also gives a nice use case, see the link above.
An extension method provides the best solution, though it doesn't totally solve all your concerns.
public class MyGenericClass<TSomeClass>
{
}
public static class MyGenericClassExtensions
{
public static void MyGenericMethod<TSomeClass, TSomeInterface>(this MyGenericClass<TSomeClass> self)
where TSomeClass : TSomeInterface
{
//...
}
}
It is still necessary to specify both types when calling MyGenericMethod, but it prevents the caller from specifying an incorrect type for TSomeClass as is possible with the approach you came up with. With this approach, the method can be called like so:
var myGenericInstance = new MyGenericClass<TSomeClass>();
myGenericInstance.MyGenericMethod<TSomeClass, TSomeInterface>();
It will be a compile error if the type parameter MyGenericClass is declared with does not match the first type parameter to MyGenericMethod.
Since the first type parameter can be inferred by the this argument, it is often possible for the compiler to infer both type parameters if their additional parameters to the method.

Why does C# not allow calling base.SomeAbstractMethod

Here is some code for the discussion
abstract class ClassA
{
public abstract void StartProcess();
}
class ClassB : ClassA
{
public override void StartProcess()
{
Console.WriteLine("ClassB: Render");
}
}
class ClassC : ClassA
{
public override void StartProcess()
{
base.StartProcess();//This is where the compiler complains
Console.WriteLine("ClassC: Render");
}
}
Before everyone jumps down my throat, let me just say that I'm fully aware of the why it does not. But there are cases where being able to do so would make sense and prevent having to declare the base class's method as virtual but with an empty implementation.
Coming from Delphi background, we could do this in Delphi and used it in our class design. If you made the mistake of calling the abstract method on the base class (at run time) you've got an "Abstract Error".
Then I wished the (Delphi) complier check me before!
Now I wish the (C#) complier would let me do this!
How weird is that?
The Questions:
Could not the complier/Jitter simply ignore such a call and issue a warning instead of error?
Do others see/feel this pain?
The case I have, where I need this is the following:
ClassA is part of a library (no control over this class)
ClassC is generated (kind of like how an ASP.NET page gets compiled or a Razor View gets compiled.
But a user of the library can define a ClassB and then ClassC will descend from ClassB instead of ClassA (when it gets generated). Similar to how ASP.NET pages normally descend from System.Web.UI.Page but if you've defined your own "base" page and other pages in your app now descendant from your base page then the generated class descends from your base page (which is turn descends from System.Web.UI.Page).
I hope that part is clear. Then looking at the code I've presented, I can't get instances of ClassC to call into the implementation of ClassB because the code gen doesn't know to include base.StartProcess().
EDIT
It seem that some people didn't quite get what I've written. So let's say you were writing the code generation part that generates ClassC that descends from ClassA. Well, since the method is anstract (in ClassA) you can't generate the line of code that calls into StartProcess() (because the complier won't allow it). As a result, if anyone define a ClassB, the code generation still won't call base.StartProcess(). This is in fact what happens in ASP.NET MVC views.
Ideally I'd like the compiler to ignore it. It ignore many things like calling dispose on a null reference for example.
I'm trying to have a discussion rather be preached to...
EDIT2
Let's assume we have a hierarchy as shown in the code above and it worked.
The opportunity we have now is that the base class, ClassA could have an implementation (in the future) for StartProcess() descendants would call into it. The only way to do this today is to define the method virtual with no body. But that feels a bit icky to me.
How could it possibly make sense to call base.StartProcess() when that's been declared to be abstract? There can't possibly be an implementation to call, so the compiler prohibits it.
Personally I like seeing errors at compile-time instead of either seeing an error at execution time or making the JITter ignore a call which I've specifically made. What if it returned a value which you assigned to a variable? What should that variable value be if the method doesn't exist?
If ClassC is going to derive from ClassB, then you won't get the problem - because you won't be calling into an abstract base method. But your code declares that it derives directly from ClassA instead, not ClassB. If ClassC is generated, it should be generated to derive from ClassB instead, which would be fine.
Personally I think the compiler is doing exactly the right thing here.
EDIT: Just to make it absolutely clear what I believe the appropriate solutions are:
If you want to be able to call base.M() from any derived class, you should make it a virtual method with a no-op implementation, instead of an abstract method.
If you have a code generator which should generate a call to base.M() only in the situations where it's generating a class whose base class has an implementation of M, then it's up to the code generator to get that right - the language shouldn't make everyone else suffer (by deferring error reporting to execution time, or worse still swallowing that error by simply performing a no-op) just because one tool has been written incorrectly.
I think the downsides of either making it an execution-time error to call an abstract base method or making it a no-op are worse than the issues described in the question.
Now an interesting language feature which could potentially be useful here would be the idea of a virtual method which forced overrides to call the base implementation either before or after the override... in a similar way to how a constructor in a derived class always has to call a constructor in the base class either directly or via another constructor. I strongly suspect that the complexity of such a feature (what would happen to the return value? How would use specify before/after semantics? What about exceptions?) would outweigh the benefits. In simple class hierarchies, the template method pattern can perform the same duty in a simpler way.
I don't think it would make sense to let the compiler compile such code.
On the other side I understand the situation in which you are. The fix should be made on the code generator: it should not generate calls to abstract methods (can be checked using reflection). If you do not have access to the code of the code generator I am afraid you do not have many options...
You could create a facade object that is derived from A but implements all abstract methods as empty virtual ones and manipulate the code generator to use it instead of A.
I see what you mean. Sometimes it might be convenient to just don't care whether a base class method is abstract or not. But, a subclass is already very coupled to its parent class, so much that the compiler knows exactly what calls are valid and issues error messages accordingly. There're no virtual base classes.
What you can do is define an adapter class. Kind of a no-op that will just implement the abstract methods to do nothing. It might not be feasible if they return values and you can't decide what default value to return. You would now derive from the adapter and call its non-abstract methods.
UPDATE
You can solve your "requirement" by using reflection. Instead of this:
base.StartProcess();
You'd use something like this:
this.BaseCall("StartProcess");
This would call StartProcess on your base class only if it's not abstract.
Here's the ugly code to make it work (which also considers parameters and default return values):
public static class BaseExtensions {
public static void BaseCall(this object self, string methodName, params object[] parameters) {
self.BaseCall(methodName, typeof(void), null, parameters);
}
public static T BaseCallWithReturn<T>(this object self, string methodName, T defaultReturn = default(T), params object[] parameters) {
return (T)self.BaseCall(methodName, typeof(T), defaultReturn, parameters);
}
private static object BaseCall(this object self, string methodName, Type returnType, object defaultReturn, object[] parameters) {
var parameterTypes = parameters.Select(p => p.GetType()).ToArray();
if (self.GetType().BaseType == null) return null;
var method = self.GetType().BaseType.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
if (method == null || method.IsAbstract) return defaultReturn;
var dm = new DynamicMethod(methodName, returnType, new Type[] { self.GetType() }.Concat(parameterTypes).ToArray(), self.GetType());
var il = dm.GetILGenerator();
PushParameters(il, parameterTypes.Length);
il.Emit(OpCodes.Call, method);
il.Emit(OpCodes.Ret);
return dm.Invoke(null, new object[] { self }.Concat(parameters).ToArray());
}
private static void PushParameters(ILGenerator il, int n) {
il.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < n; ++i) {
switch (i+1) {
case 1: il.Emit(OpCodes.Ldarg_1); break;
case 2: il.Emit(OpCodes.Ldarg_2); break;
case 3: il.Emit(OpCodes.Ldarg_3); break;
default: il.Emit(OpCodes.Ldarg_S, i+1); break;
}
}
}
}
Is it worth it? I'll let you decide.
You are deriving ClassC from ClassA, what would you expect base.StartProcess to actually do?
Do you really mean to derive from ClassB

Categories