Delegating dynamic object resolution to other instances - c#

I'm currently hosting IronPython in a .NET 2.0 application.
I want to create a class (in C#) whose instances can be "extended" by plugin instances. That means, each member access which is unresolvable on my instance should be forwarded to the appropriate plugin instance providing that member. My object will hold a private container with those plugin instances then.
AFAICS, the way to go there is via deriving from DynamicObject. The first step was easy so far that TryGetMember is called whenever python code uses "unknown" members of my instance. I also could return objects and delegates which could be used from the python code.
But, somehow, I got stuck when trying to use the DLR to perform the "subsearch" on the plugin instance and e. G. return a method or property of the plugin instance in the way IronPython expects it.
Any hints are welcome!
Thanks!
Edit: My original question was not formulated clear enough, sorry. Here some points:
The solution has to run with plain .NET 2.0, no .NET 3.5 or 4.0 allowed.
The plugin list are per instance (that means each instance can have a different - but immutable - list of plugin objects).
The plugin objects should be plain C# objects with all public members (or at least methods and properties) mapped.
Collision detection is not important.
Thanks again.

What it sounds like you want to do is have your plugin instances typed to object or dynamic (versus having them typed to some interface where you effectively pass through the TryGetMember request) and then perform a dynamic binding against another object. Luckily for you the DLR interop protocol allows for exactly this scenario! It'll require to drop down to the IDynamicMetaObjectProvider layer instead of using DynamicObject but it's actually pretty simple. I'll show you a simple example using InvokeMember that works end-to-end w/ C# 4.0. You'll need to go and do the rest of the operations - in particular IronPython will use GetMember instead of InvokeMember. But that's a straight forward process.
First an explanation of how you do it. At the IDMOP level the DLR deals with meta objects and languages request operations from meta objects and those meta objects return more meta objects. You can also ask the language to perform it's default binding and most importantly you can provide to it a suggestion of what to do when things go wrong.
Based upon that you can ask the language to try and bind to each one of your plugins and your own object. Depending on whether you want plugins to have precedence, or your dynamic object, you can perform the binding to yourself last. This sample demonstrates both techniques based upon the member names.
So without further delay, here it is:
using System;
using System.Dynamic;
using System.Linq.Expressions;
namespace ConsoleApplication10 {
class Program {
static void Main(string[] args) {
dynamic dynamicObj = new MyDynamicObject(new TestPlugin());
dynamicObj.Foo();
dynamicObj.Bar();
Console.ReadLine();
}
}
public class TestPlugin {
public void Foo() {
Console.WriteLine("TestPlugin Foo");
}
public void Bar() {
Console.WriteLine("TestPlugin Bar");
}
}
class MyDynamicObject : IDynamicMetaObjectProvider {
internal readonly object[] _plugins;
public void Foo() {
Console.WriteLine("MyDynamicObject Foo");
}
public void Bar() {
Console.WriteLine("MyDynamicObject Bar");
}
public MyDynamicObject(params object[] plugins) {
_plugins = plugins;
}
class Meta : DynamicMetaObject {
public Meta(Expression parameter, BindingRestrictions restrictions, MyDynamicObject self)
: base(parameter, restrictions, self) {
}
public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {
// get the default binding the language would return if we weren't involved
// This will either access a property on MyDynamicObject or it will report
// an error in a language appropriate manner.
DynamicMetaObject errorSuggestion = binder.FallbackInvokeMember(this, args);
// run through the plugins and replace our current rule. Running through
// the list forward means the last plugin has the highest precedence because
// it may throw away the previous rules if it succeeds.
for (int i = 0; i < Value._plugins.Length; i++) {
var pluginDo = DynamicMetaObject.Create(Value._plugins[i],
Expression.Call(
typeof(MyDynamicObjectOps).GetMethod("GetPlugin"),
Expression,
Expression.Constant(i)
)
);
errorSuggestion = binder.FallbackInvokeMember(pluginDo, args, errorSuggestion);
}
// Do we want DynamicMetaObject to have precedence? If so then we can do
// one more bind passing what we've produced so far as the rule. Or if the
// plugins have precedence we could just return the value. We'll do that
// here based upon the member name.
if (binder.Name == "Foo") {
return binder.FallbackInvokeMember(this, args, errorSuggestion);
}
return errorSuggestion;
}
public new MyDynamicObject Value {
get {
return (MyDynamicObject)base.Value;
}
}
}
#region IDynamicMetaObjectProvider Members
public DynamicMetaObject GetMetaObject(System.Linq.Expressions.Expression parameter) {
return new Meta(parameter, BindingRestrictions.Empty, this);
}
#endregion
}
public static class MyDynamicObjectOps {
public static object GetPlugin(object myDo, int index) {
return ((MyDynamicObject)myDo)._plugins[index];
}
}
}
Running this prints:
MyDynamicObject Foo
TestPlugin Bar
Showing that for Foo members we prefer the binding on the actual object, and for Bar members we prefer Bar. If you add access to a third Baz member it produces C#'s runtime binder exception. If this was called from IronPython we'd produce an AttributeError to Python programs (a MissingMemberException in .NET) and a JavaScript implement should return undefined to their programs.
So you get not only your extensible plugin system you also easily get the correct behavior in any langauge which consumes your object.

Related

Inheritance in c# using reflection

I am in a situation where i have to inherit a class and access its protected method to get a value.
Due to some weird situations i have most of my code in reflection and i m hoping if i have any chance to get this working using reflection.
To make things more clear,
Below is the class
public class Converter: BaseConverter
{
public Converter();
protected override object StringToValue();
}
I need to do below to get the functionality working.
public class myclass:Converter
{
public StringToValue()
{
base.StringToVaue();
}
}
However I cannot use direct reference of Converter dll in my project . So i am handicapped here to use inheritance and myclass : converter. So how can i approach this using reflection which would be to basically make myclass inherit the converter class at runtime. I am not sure if it makes sense or not however it seems to me that its where i am trying to head towards to get an answer
You can use TypeBuilder to create a whole new type at runtime via reflection. Of course ultimately you need a reference to the assembly which contains Converter to inherent from it. Make sure to check out the MSDN example of TypeBuidler. You need to call ModuleBuilder.DefineType() which has an overload to specify the parent type.
But if you go that way you have to do everything with reflection including emitting the methods. I don't fully understand your restrictions so that's the best answer I could think of but I don't really like it ;)
While we're talking about hacking: Do you really need to inherit from Converter or do you only need to access its methods? In case you only need the methods you could simply hold an instance of Converter as an attribute of type object and call the protected method via refletion inside your public StringToValue method.
EDIT:
As you ask for sample code. With reflection you can bypass the class security mechanism of C#, which means you're able to call non-public methods on any object. First you need the Type. Because you can't write it out in C# you need to get it some other way. Then you can create an instance of that type with Activator. You also need to obtain information about the method you want to call. It makes sense to cache this information because the processes of reading that information with reflection is kinda slow. Finally you can use the MethodInfo to actually call the method.
I haven't tested that code because I don't have a machine to do so right now.
class myclass
{
object internalConverter;
MethodInfo converterStringToValueMethod;
public myclass()
{
// Here you need a reference to the assembly which contains the Converter type
Assembly asm = Assembly.Load("xxx.dll"); // Name of the assembly which contains Converter
Type converterType = asm.GetType("Converter");
this.internalConverter = Activator.CreateInstance(converterType);
this.converterStringToValueMethod = converterType.GetMethod("StringToValue", BindingFlags.NonPublic | BindingFlags.Instance);
}
public object StringToValue()
{
return converterStringToValueMethod.Invoke(internalConverter, null);
}
}
This should do what you want without inheritance:
using System;
using System.Reflection;
namespace Test
{
class Converter
{
string Value;
public Converter(string test)
{
Value = test;
}
protected object StringToValue()
{
return Value;
}
}
class myclass
{
object Unknown;
public myclass(object other)
{
Unknown = other;
}
MethodInfo originalFunction;
public object StringToValue()
{
if (originalFunction == null)
{
originalFunction = Unknown.GetType().GetMethod("StringToValue", BindingFlags.NonPublic | BindingFlags.Instance);
}
return originalFunction.Invoke(Unknown, null);
}
}
class Test
{
[System.STAThread]
public static void Main(string[] args)
{
Converter unknown = new Converter("TEST");
myclass mine = new myclass(unknown);
Console.WriteLine(mine.StringToValue());
Console.ReadLine();
}
}
}
This is a bad idea for a number of reasons, but if you are sure it is what you need...

How to get non-static MethodInfo using method name (not in string, not searching in class type)

Consider following code:
public class Test
{
[System.AttributeUsage(System.AttributeTargets.Method)]
class MethodAttribute : System.Attribute
{
public MethodAttribute(System.Reflection.MethodInfo methodInfo)
{
}
}
public void Foo()
{
}
[Method(Test.Foo)] //< THIS IS THE IMPORTANT LINE
public void Boo()
{
}
}
I want to store MethodInfo instance of Foo in attribute of Boo, but problem is, that I cannot use Foo nor Test.Foo to get instance of MethodInfo. I can NOT use typeof(Test).GetMethod("Foo") (not my decision).
Important information:
Generated error is: error CS0120: An object reference is required to access non-static member `Test.Foo()'
I'm coding in Unity3D which is using Mono, not .Net. (more info http://docs.unity3d.com/410/Documentation/ScriptReference/MonoCompatibility.html )
Windows 7
Absolutely unimportant information:
Why I cannot use typeof(Test).GetMethod("Foo"): I'm not allowed. It's not in my power to change this decision. I can not. (Also, personally, I would like to avoid it anyway as it needs to do some lookup instead of getting statically the data. Also it won't be changed automatically during refactoring and will be checking run-time, not compile-time.)
Why I want to do this: later in code, I want to create a delegate of Boo() (this time normally, with an instance) and use in special even system or something. Before it's called, this attribute allows to setup method to be called in prepare for main event (it's optional, it can be null) and I know how to create a delegate when I have an object and a method info.
Why I cannot just provide both delegates when registering or something: because class containing these methods is not always the one who registers to event source, I need to keep the registration code as simple as possible. In other words, I want to avoid situation when person writing method responsible for connecting forgots to add this preparation delegate.
use expression :
static public class Metadata<T>
{
static public PropertyInfo Property<TProperty>(Expression<Func<T, TProperty>> property)
{
var expression = property.Body as MemberExpression;
return expression.Member as PropertyInfo;
}
}
var foo = Metadata<Test>.Property(test => test.Foo);

C# dynamic executing function by its name?

I have a dynamic variable
dynamic d = GetSomeObject();
Sometime , in future, a user send me a function to execute ( its name) e.g "UsersGetAll"
So I need to do something like : d.UsersGetAll()
I can do it with reflection. But I want to use the DLR .
Does the only solution of doing this is to have MyObject inherit from DynamicObject and then implement TryInvokeMember?
What if I don't have control over the class ?
As Jon notes, the following really only applies if you suspect that the type is providing the method at runtime via the DLR; in most simple cases, reflection will be easier.
dynamic is intended when you know the method name but not the target. If you don't know the method name it is tricker. The tricky bit, perhaps, is ensuring you keep the call-site so that it can be re-used (which is how the DLR maintains performance). One cheeky way would be a static utility class that keeps track of invoked methods. Here's an example - note that it gets much messier if you need to handle parameters:
using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Runtime.CompilerServices;
public class Foo
{
public object Bar() { return "I was here"; }
}
static class Program
{
static void Main()
{
object obj = new Foo();
object result = DynamicCallWrapper.Invoke(obj, "Bar");
Console.WriteLine(result);
}
}
static class DynamicCallWrapper
{
// Hashtable has nice threading semantics
private static readonly Hashtable cache = new Hashtable();
public static object Invoke(object target, string methodName)
{
object found = cache[methodName];
if (found == null)
{
lock (cache)
{
found = cache[methodName];
if(found == null)
{
cache[methodName] = found = CreateCallSite(methodName);
}
}
}
var callsite = (CallSite<Func<CallSite, object,object>>)found;
return callsite.Target(callsite, target);
}
static object CreateCallSite(string methodName)
{
return CallSite<Func<CallSite, object, object>>.Create(
Binder.InvokeMember(
CSharpBinderFlags.None, methodName, null, typeof(object),
new CSharpArgumentInfo[] {
CSharpArgumentInfo.Create(
CSharpArgumentInfoFlags.None, null) }));
}
}
I can do it with reflection. But I want to use the DLR.
Why? Assuming this is a "normal" object which isn't actually going to respond dynamically, reflection is going to be the easiest approach here.
The dynamic feature in C# 4 (in terms of the language feature) does absolutely nothing to help you here. It only allows dynamic binding of member names within C# source code.
Now you could:
Start an IronPython session, and create a tiny Python script to call the method using dynamic binding.
Use CSharpCodeProvider to compile some C# code using dynamic with the relevant method name, then execute that code.
Look at the generated code for your d.UsersGetAll() call, and basically emulate that.
All of these options are likely to be harder than reflection, if all you want it so call a "normal" method on a "normal" object, and you happen to only know the name at execution time.

Strongly-typed property reference to multiple classes with no common interface (C#)

The System.Windows.Documents namespace includes a number of classes with an Inlines property of type InlineCollection. For example, the Paragraph, Bold and Hyperlink classes all have this property.
Each of these classes is decorated with ContentPropertyAttribute ...
[ContentPropertyAttribute("Inlines")]
public class Paragraph : Block
... which means that it is easy enough, using reflection, to detect that a given object exposes this property.
However, I need to be able to access this property in a strongly-typed manner across a selection of the types that implement it.
I am a little surprised that Microsoft didn't make all these classes implement an "IInlineContainer" interface, which would have made type checking and casting very easy.
However, in the absence of such an interface, is there any way to fake this polymorphic functionality, ideally without littering my code with lots of conditions and type checking?
Many thanks for your ideas,
Tim
Edit:
Thanks for your suggestions. A number of people have suggested the idea of a wrapper class, but this is not possible in my situation, as the target objects are not created by my code, but by the other classes in the .NET framework, for example the Xaml parser or the RichTextBox control (in which the containing FlowDocument is being edited).
Edit 2:
There have been several great suggestions here and I thank everyone who shared their ideas. The solution I have chosen to implement employs extension methods, which was suggested by #qstarin, although I have refined the concept to suit my needs, as follows:
public static InlineCollection GetInlines(
this FrameworkContentElement element)
{
if (element == null) throw new ArgumentNullException("element");
if (element is Paragraph)
{
return ((Paragraph) element).Inlines;
}
else if (element is Span) // also catches Bold, Italic, Unerline, Hyperlink
{
return ((Span)element).Inlines;
}
else
{
return null;
}
}
Although this approach requires conditional logic and type casting (which I said I wanted to avoid) the use of extension methods means that it only needs to be implemented in one place, leaving my various calling methods uncluttered.
Extension methods.
public static class InlineContainerExtensions {
public static InlineContainer GetInlines(this Paragraph inlineContainer) {
return inlineContainer.Inlines;
}
public static InlineContainer GetInlines(this Bold inlineContainer) {
return inlineContainer.Inlines;
}
}
If you didn't need to access it in a strongly-typed manner, but just without reflection, you could use dynamic:
dynamic doc = new Bold()
doc.InlineCollection. ...
doc = new Paragraph()
doc.InlineCollection. ...
Another option is to define a wrapper, that exposes a property with the same name, and has an overloaded constructor that takes Bold, Paragraph, etc.
You could implement a wrapper class that exposes an Inlines property and delegates via reflection to the contained object.
Decide if you want to validate that the wrapped object indeed has Inlines in your constructor or when trying to reference it
Employ the Adapter Pattern, write one class for each of those classes you wish to handle, effectively wrapping them in a layer implementing a common layer.
To make the classes discoverable, I would use reflection, tag each such class with an attribute for which class they handle, ie.:
[InlineContainerAdapter(typeof(SpecificClass1))]
public class WrapSpecificClass1 : IInlineContainer
and use reflection to find them.
This would give you several benefits:
You don't have to deal with dynamic, or similar solutions
While you have to use reflection to find the classes, the code you're actually executing once you've created the adapter is 100% yours, hand-coded
You can create adapters for classes that doesn't really implement what you need in the same manner as the rest, by just writing the adapter different
If this sounds like an interesting solution, leave a comment and I'll put up a working complete example.
One way of doing this (apart from using dynamic, which is the easiest solution IMO), you can create dynamically generated methods to return the inlines:
Func<object, InlineCollection> GetInlinesFunction(Type type)
{
string propertyName = ...;
// ^ check whether type has a ContentPropertyAttribute and
// retrieve its Name here, or null if there isn't one.
if (propertyName == null)
return null;
var p = Expression.Parameter(typeof(object), "it");
// The following creates a delegate that takes an object
// as input and returns an InlineCollection (as long as
// the object was at least of runtime-type "type".
return Expression.Lambda<Func<object, InlineCollection>>(
Expression.Property(
Expression.Convert(p, type),
propertyName),
p).Compile();
}
You'd have to cache these somewhere, though. A static Dictionary<Type, Func<object, InlineCollection>> comes to mind. Anyway, when you have, you can simply make an extension method:
public static InlineCollection GetInlines(this TextElement element)
{
Func<object, InlineCollection> f = GetCachedInlinesFunction(element.GetType());
if (f != null)
return f(element);
else
return null;
}
Now, with this in place, just use
InlineCollection coll = someElement.GetInlines();
Because you can check in your GetCachedInlinesFunction whether the property really exists or not, and handle that in a neat fashion, you won't have to litter your code with try catch blocks like you have to when you're using dynamic.
So, your dream-code would be:
foreach (var control in controls) {
var ic = control as IInlineContainer;
if (ic != null) {
DoSomething(ic.Inlines);
}
}
I don't see why you don't want to create a strongly typed wrapper class that uses reflection. With this class (no error handling):
public class InlinesResolver {
private object _target;
public InlinesResolver(object target) {
_target = target;
}
public bool HasInlines {
get {
return ResolveAttribute() != null;
}
}
public InlineCollection Inlines {
get {
var propertyName = ResolveAttribute().Name;
return (InlineCollection)
_target.GetType().GetProperty(propertyName).GetGetMethod().Invoke(_target, new object[] { });
}
}
private ContentPropertyAttribute ResolveAttribute() {
var attrs = _target.GetType().GetCustomAttributes(typeof(ContentPropertyAttribute), true);
if (attrs.Length == 0) return null;
return (ContentPropertyAttribute)attrs[0];
}
}
You could almost get to your dream-code:
foreach (var control in controls) {
var ir = new InlinesResolver(control);
if (ir.HasInlines) {
DoSomething(ir.Inlines);
}
}
You could always superclass them (e.g. InlineParagraph, InlineBold, etc) and have each of your superclasses implement an IInlineContainer interface like you suggested. Not the quickest or cleanest solution, but you at least have them all descending from the same interface.
Depending on your use-case, you could create a public Api that delegated its work to a private method that takes a dynamic. This keeps the strong typing for your public Api and eliminates code duplication, even though it falls back to using dynamic internally.
public void DoSomethingwithInlines(Paragraph p) {
do(p);
}
public void DoSomethingwithInlines(Bolb b) {
do(b);
}
private void do(dynamic d) {
// access Inlines here, using c# dynamic
}

Does new 'dynamic' variable type in .NET 4.0 solve the single/multiple method dispatch issue in CLR?

The problem of single dispatch is mostly familiar to people engaged in coding with statically typed languages like Java and C#. The basic idea is:
While the runtime polymorphism allows us to dispatch to the right method call according to the type (runtime type) of receiver, for example:
IAnimal mything = new Cat();
mything.chop();
The method call will be performed according to the runtime type of mything, namely Cat.
This is the single dispatch capability (which is present in Java/C#).
Now, if you need to dispatch not only on the runtime type of receiver, but on the types of (multiple) arguments either, you face a little problem:
public class MyAcceptor {
public void accept (IVisitor vst) {...}
public void accept (EnhancedConcreteVisitor vst) {...}
}
The second method never gets called, because in our 'consumer' code we just tend to treat different types of objects (visitors in my example) by their common supertype or interface.
That's why I ask - because dynamic typing allows the multiple dispatch polymorphism and C# 4.0 has that dynamic keyword ;)
Yes, dynamic typing allows multiple dispatch - and no, you don't have to create your own dynamic object to do it.
Suppose we wanted to implement Enumerable.Count() ourselves, and we didn't want a load of "if (source is IList)" tests in our code. We could write it like this:
public static class Enumerable
{
public static int Count<T>(this IEnumerable<T> source)
{
dynamic d = source;
return CountImpl(d);
}
private static int CountImpl<T>(ICollection<T> collection)
{
return collection.Count;
}
private static int CountImpl(ICollection collection)
{
return collection.Count;
}
private static int CountImpl<T>(string text)
{
return text.Length;
}
private static int CountImpl<T>(IEnumerable<T> source)
{
// Fallback
int count = 0;
foreach (T t in source)
{
count++;
}
return count;
}
}
I'm not saying it would be a good idea, but that's how it would work :)
Note that you need to be careful not to introduce situations where you could end up with an ambiguous call for some types. This wouldn't be an issue using classes for parameters, but consider that a single class can implement multiple interfaces.
Yes, you can create DLR types that do arbitrarily complex dispatch. Check out http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

Categories

Resources