patterncsharpMinor
Wrapper for dynamic behavior
Viewed 0 times
wrapperbehaviorfordynamic
Problem
I am writing a wrapper for dynamic behavior in C#. If I use
GetMethod(), then an exception is thrown when there is more than one method (overloads). I figure it will become apparent at runtime that if there is an argument mismatch anyway. Is this a good way to solve the problem?public class StaticMembersDynamicWrapper : DynamicObject
{
private Type _type;
public StaticMembersDynamicWrapper(Type type) { _type = type; }
// Handle static methods
public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
{
var methods = _type
.GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public)
.Where(methodInfo => methodInfo.Name == binder.Name);
var method = methods.FirstOrDefault();
if (method != null)
{
result = method.Invoke(null, args);
return true;
}
result = null;
return false;
}
}Solution
The order the method infos are returned in dose not appear to be a defined one, I would suggest filtering on argument types to avoid the risk of it all crumbling to dust when the order changes.
Also you may want to consider the case when a method is defined on both the base class and the subclass.
Hiding static methods like this should probably be frowned upon, but all the same I would suggest selecting the method with the most specific declaring type. Just to be safe.
Edit:
Another possibility worth exploring is the use of Type.InvokeMember(). This already takes the argument types and method hiding into account for you.
Also you may want to consider the case when a method is defined on both the base class and the subclass.
class A
{
public static void DoAwsomeStuff()
{
// really awsome stuff.
}
}
class B : A
{
public static void DoAwsomeStuff()
{
// different but still awsome stuff.
}
}Hiding static methods like this should probably be frowned upon, but all the same I would suggest selecting the method with the most specific declaring type. Just to be safe.
MethodInfo method = null;
foreach(var current in methods)
{
if(method == null || current.DeclaringType.IsAssignableFrom(method.DeclaringType))
{
method = current;
}
}Edit:
Another possibility worth exploring is the use of Type.InvokeMember(). This already takes the argument types and method hiding into account for you.
try
{
result = _type.InvokeMember(
binder.Name,
BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.InvokeMethod,
null,
null,
args
);
return true;
}
catch(MissingMethodException)
{
result = null;
return false;
}Code Snippets
class A
{
public static void DoAwsomeStuff()
{
// really awsome stuff.
}
}
class B : A
{
public static void DoAwsomeStuff()
{
// different but still awsome stuff.
}
}MethodInfo method = null;
foreach(var current in methods)
{
if(method == null || current.DeclaringType.IsAssignableFrom(method.DeclaringType))
{
method = current;
}
}try
{
result = _type.InvokeMember(
binder.Name,
BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy | BindingFlags.InvokeMethod,
null,
null,
args
);
return true;
}
catch(MissingMethodException)
{
result = null;
return false;
}Context
StackExchange Code Review Q#2184, answer score: 2
Revisions (0)
No revisions yet.