Click here to Skip to main content
Email Password   helpLost your password?
Screenshot - Duck.jpg

Introduction

In this installment of the series, I'll show you how you can use LinFu.DynamicObject to add dynamic language features to your code. I'll also discuss how LinFu.DynamicObject does this behind the scenes and briefly touch upon how you can use it in conjunction with the new language features coming up in C# 3.0. Note: If you're wondering what the entire LinFu Framework is about, click here.

Background

Since the version 1.0 release of the .NET Framework, many developers have been clamoring for features such as multiple inheritance and mixins. Unfortunately, due to the complexity of implementing multiple inheritance, mixins and the trouble those features entail, Microsoft left those features out of the .NET Framework.

Until recently, these feature requests have been largely ignored. However, thanks to upcoming dynamic languages like IronPython and IronRuby, Microsoft is finally starting to provide those language features that everyone else has been asking for. However, in order to use those features in your application, you have to switch your codebase to a new programming language. That might not be a feasible option if one has deadlines to meet and milestones to reach.

This scenario effectively leaves us developers with two options: One can either find a workaround for the statically typed, single-inheritance limitations imposed by C#, VB.NET and the CLR, or one can take Reflection.Emit into their own hands and implement those features themselves. Most sane developers would have taken the first option. Thankfully, I am not a sane person when it comes to coding and thus, LinFu.DynamicObject was born.

What You Need to Know

This article assumes that you know enough about dynamic language features such as mixins, multiple dispatch and the like. It also assumes that you understand enough about dynamic proxies to make use of the library.

Features and Usage

One of the most notable features about LinFu.DynamicObject and the rest of the LinFu library is that it is language-independent. Although the examples shown here are done in C#, anyone can easily use it in the same way in other languages, such as VB.NET. Aside from whichever programming language you wish to use, LinFu.DynamicObject supports the following features:

Late Binding

Unlike typical method calls made by an application, LinFu.DynamicObject doesn't know which method you will be using until the application is running. What LinFu.DynamicObject does is actually determine which method you'll be using just by looking at the name of the method that you're calling, and the runtime arguments that are being passed to that method.

Here's an example. Suppose that I had an instance of a System.IO.StringWriter class, which has multiple overloads of the WriteLine() method:

StringWriter writer = new StringWriter();
DynamicObject dynamic = new DynamicObject(writer);

// Note that there are 18 overloads for TextWriter.WriteLine()

// Call WriteLine(string text);
dynamic.Methods["WriteLine"]("Hello, World!");

// Call Writeline(bool value);
dynamic.Methods["WriteLine"](false);

No matter what the method signature, LinFu.DynamicObject makes it easy to perform late-bound calls to objects at runtime.

Multiple Dispatch

As I mentioned earlier, LinFu.DynamicObject can match any method signature with any arbitrary number of arguments. Using this feature, I can do things that would otherwise be difficult (or impossible) to implement just by using the native features of a statically typed language alone. For example, suppose that I had a class named CollisionManager that managed a bunch of shapes on the screen and that I wanted it to perform a certain set of actions when a certain set of shapes Collide():

public class CollisionManager
{
   // Overload #1
   public void Collide(Circle circle, Square square, Triangle triangle)
   {
      Console.WriteLine("Overload #1 Called");
   }

   // Overload #2
   public void Collide(Square square, Circle circle, Triangle triangle)
   {
      Console.WriteLine("Overload #2 Called");
   }

   // Overload #3
   public void Collide(Triangle triangle, Square square, Circle circle)
   {
      Console.WriteLine("Overload #3 Called");
   }

   // Overload #4
   public void Collide(Triangle triangle, Circle circle)
   {
      Console.WriteLine("Overload #4 Called");
   }
}

A Collision with Insanity

Now, suppose that I wanted to be able to call any one of these overloads, depending on both the order and type of each parameter, using only a single method call. Needless to say, doing something like this in a statically typed language is an outright nightmare. Fortunately, with LinFu.DynamicObject, you no longer have to do this by hand. Calling those overloaded methods is just as simple as:

// Wrap the CollisionManager instance
DynamicObject dynamic = new DynamicObject(new CollisionManager());

object[] list1 = new object[]{new Circle(), new Square(), new Triangle()};
object[] list2 = new object[]{new Square(), new Circle(), new Triangle()};
object[] list3 = new object[]{new Triangle(), new Square(), new Circle()};
object[] list4 = new object[]{new Circle(), new Triangle()};

// Call Overload #1
dynamic.Methods["Collide"](list1);

// Call Overload #2
dynamic.Methods["Collide"](list2);

// Call Overload #3
dynamic.Methods["Collide"](list3);

// Call Overload #4
dynamic.Methods["Collide"](list4);

As you can see from the example above, LinFu.DynamicObject makes it easy to call the appropriate Collide() method in spite of the number of overloads that might exist for that particular method. It can easily distinguish between the different method signatures. It does all of the boilerplate work for the developer, allowing you to focus on the more important tasks at hand.

Dynamic Methods

DynamicObject also allows you to dynamically add methods to it at runtime by using the following methods:

public void AddMethod(string methodName, MulticastDelegate body);
public void AddMethod(string methodName, CustomDelegate body, 
    Type returnType,   params Type[] parameters);

The first overload allows you to add a method using an existing delegate type (such as a delegate type that exists at compile time), while the second overload allows you to define a method with a particular signature and method body. I'll go over each example below:

Using an Existing Delegate Type

public delegate int MathOperation(int a, int b);

public class Program
{
   public static void Main()
   {
       // Define the method body
       MathOperation body = delegate(int a, int b) { return a + b; };

       // Create an empty DynamicObject
       // that wraps around a System.Object
       DynamicObject dynamic = new DynamicObject();
       dynamic.AddMethod("Add", body);

       // This will return '2'
       int result = (int)dynamic.Methods["Add"](1, 1);
   }
}

In this example, I took an anonymous delegate of the type MathOperation and gave it a method body. Using that body, I then created a method named Add on DynamicObject. Once the method was added, the only thing left to do was invoke it, giving 2 as the result. Using an existing delegate type can be handy if you already have an instance of a particular delegate in memory (such as an anonymous delegate) and you want to make it a part of DynamicObject. The only problem with this approach is that it only allows you to add methods based on delegate types that exist at compile time. This can prevent a developer from generating methods at runtime. That is where the second overload can be used:

Using the CustomDelegate Type

// Note: The differences are highlighted in bold
public class Program
{
   public static void Main()
   {
       // Notice there isn't a preexisting
         // MathOperation delegate in this example
       CustomDelegate body = delegate(object[] args)
       {
          int a = (int)args[0];
          int b = (int)args[1];
          return a + b;
       };

       // Create an empty DynamicObject
       // that wraps around a System.Object
       DynamicObject dynamic = new DynamicObject();
       Type[] parameters = new Type[] {typeof (int), typeof (int)};
       Type returnType = typeof (int);

       dynamic.AddMethod("Add", body, returnType, parameters);

       // This will return '2'
       int result = (int)dynamic.Methods["Add"](1, 1);
   }
}

Using the CustomDelegate type allows me to define the body of the method without tying the method signature to any specific parameter types. In this example, I extracted the first two arguments from the args array defined in the body of the CustomDelegate instance. Just as I did in the previous example, I then simply added the two numbers together and returned the result. The difference in this example was that I actually had to specify both the method return type and the method parameter types when I used the CustomDelegate type as the method body.

The Choice is Yours

Other than those differences that I just mentioned, the two overloads work the same way. It's really up to you to decide whether you prefer the flexibility of CustomDelegate or to use the signature of your own predefined delegate. In my opinion, the second choice would be the better option, since it is more dynamic and thus easier to maintain.

Duck Typing

Another one of LinFu.DynamicObject's strengths is that it can make itself look and act like nearly any interface or non-sealed class. For example, suppose that I have the following interface defined:

public interface IMath
{
   int Add(int a, int b);
}

Walking Like a Duck

Drawing on the examples from the previous section, I can take the same DynamicObject and make it look and act like IMath:

IMath math = null;

// Make sure that the dynamic object
// can indeed act like an IMath object
int result = 0;
if(dynamic.LooksLike<IMath>())
{
   math = dynamic.CreateDuck<IMath>();
   result = math.Add(1, 1);
}

Every time the CreateDuck() method is called, DynamicObject generates a proxy that implements the given class or interface (e.g. IMath). That proxy, in turn, forwards all of its calls back to DynamicObject to handle the actual method implementation. So, every time the IMath.Add() method is invoked by the client, the proxy is calling DynamicObject directly using the following method call:

// This is equivalent to IMath.Add(1, 1)
return dynamic.Methods["Add"](1,1);

A Duck or Not a Duck?

In addition to acting like an IMath instance, DynamicObject can also determine whether or not it has a sufficient number of compatible methods and properties to implement that interface using the LooksLike() method. This is useful if you want to make sure that DynamicObject adheres to a specific interface type.

Mixins

LinFu.DynamicObject also supports "mixing" (or combining) itself with other object instances to make it appear as if all of the mixed items form a cohesive class at runtime. In general, it supports three types of mixins:

Standard Object References

A DynamicObject instance can mix itself with another object reference (that is, a plain old System.Object-derived class), take all of the methods and properties of that class and make it a part of that DynamicObject instance itself. For example, suppose that I wanted to implement an interface named IPerson:

public interface IPerson
{
   string Name { get; }
   int Age { get; }
}

...and suppose that I wanted to implement that interface using instances of two hypothetical mixins named Nameable and HasAge:

public class Nameable
{
   private string _name;

   public Nameable(string name)
   {
     _name = name;
   }
   public string Name
   {
     get { return _name;  }
   }
}

public class HasAge
{
   private int _age;
   public HasAge(int age)
   {
     _age = age;
   }
   public int Age
   {
      get { return _age; }
   }
}

As you can see, there's really nothing special about these two mixins. Creating an implementation of the IPerson interface is as simple as:

DynamicObject dynamic = new DynamicObject();

IPerson person = null;

// This will return false
bool isPerson = dynamic.LooksLike<IPerson>();

// Implement IPerson
dynamic.MixWith(new HasAge(18));
dynamic.MixWith(new Nameable("Me"));

// Now that it's implemented, this
// will be true
isPerson = dynamic.LooksLike<IPerson>();

if (isPerson)
   person = dynamic.CreateDuck<IPerson>();

// This will return "Me"
string name = person.Name;

// This will return '18'
int age = person.Age;

The above example would work for simple cases where the mixins are simply property holders, but what if a mixin had more complicated operations that needed to have access to DynamicObject?

Mixin-Aware Instances

For more advanced scenarios, a mixin itself might need to interact with the other mixins that are a part of the current DynamicObject instance. If you need to have your mixins interact with DynamicObject itself, all you need is to implement the following interface with your mixin:

public interface IMixinAware
{
    DynamicObject Self { get; set; }
}

public class MyMixin : IMixinAware
{
  private DynamicObject _self;
  public void DoSomething()
  {
    DynamicObject dynamic = Self;
    // Perform some operations on the DynamicObject
    IMath math = dynamic.CreateDuck<IMath>();
    math.Add(1, 1);
  }
  public DynamicObject Self
  {
    get { return _self; }
    set { _self = value;}
  }
}

public class MathMixin : IMath
{
   public int Add(int a, int b)
   {
      return a + b;
   }
}

The next thing that you have to do is call the MixWith() method using your new mixin class:

// ...somewhere in your program...
DynamicObject dynamic = new DynamicObject();
dynamic.MixWith(new MathMixin());

// Note: Once the MixWith() method is called,
// the DynamicObject will actually call
// IMixinAware.Self = this; on the new mixin
dynamic.MixWith(new MyMixin());

Any mixin class that implements the IMixinAware interface has the ability to access (and modify) the attached DynamicObject at will and at any given time. In my opinion, the power that this feature gives is mind-boggling. For now, I think I'll leave it in the capable hands of the readers to figure out what to do with this. Anyway, let's move on to the next part: mixing DynamicObjects with other DynamicObjects.

Combining DynamicObjects

Combining two DynamicObjects is as easy as:

public class GreeterMixin
{
    public void Greet()
    {
       Console.WriteLine("Hello, World!");
    }
}
public class OtherMixin
{
    public void DoSomething()
    {
       Console.WriteLine("DoSomething() called");
    }
}

class Program
{
    static void Main(string[] args)
    {
       DynamicObject first = new DynamicObject(new GreeterMixin());
       DynamicObject second = new DynamicObject(new OtherMixin());

       // The two DynamicObjects can combine into a single object
       DynamicObject combined = first + second;
       combined.Methods["Greet"]();
       combined.Methods["DoSomething"]();
    }
}

When two DynamicObjects are combined, it results in a new DynamicObject that has all of the methods and mixins of both previous instances. This can cause a problem, however, if two dynamic objects have two of the same type of mixins. In the event of a mixin conflict, which mixin gets used?

Resolving Conflicts with Duplicate Mixins

There's no easy way to resolve this issue. In fact, this is probably one of the reasons why Microsoft left mixins and multiple inheritance out of the CLR in the first place. So, in the absence of a perfect solution, I decided to take the simplest one and apply it to LinFu.DynamicObject: The first mixin in DynamicObject is the first to execute. Here's an example:

public class GreeterMixin
{
    private string _message;
    public GreeterMixin(string message)
    {
      _message = message;
    }
    public void Greet()
    {
       Console.WriteLine(_message);
    }
}

public static class Program
{
   public static void Main()
   {
      GreeterMixin first = new GreeterMixin("Hello, World!");
      GreeterMixin second = new GreeterMixin("Hello, CodeProject!");

      DynamicObject dynamic = new DynamicObject();
      dynamic.MixWith(first);
      dynamic.MixWith(second);

      // This will display "Hello, World!"
      dynamic.Methods["Greet"]();
   }
}

In this scenario, the first GreeterMixin will always be the first and only mixin to execute. This is because DynamicObject will search all of its mixins and methods for the first method that has the same method name and a compatible method signature and it will execute just that one method. Every other method after the first method found will simply be ignored.

Points of Interest

Bypassing Sealed Methods and Types: "Duck Taping"

One problem that has dogged many developers when using various class libraries is when the given library author seals a type and prevents its methods from being overridden. In normal circumstances (that is, in statically typed languages), this is akin to hitting a brick wall. Fortunately, this isn't the case with LinFu.DynamicObject. Generally, you can bypass a sealed type using the following steps:

Create (or Find) an Interface That Looks Like Your Target Type

The first thing that you need to do is figure out which methods or properties you will override in the target class. Then create an interface that is similar to the list of methods that you will be overriding. In this example, suppose that I wanted to override System.Data.SqlConnection so that I got a notification every time I called IDbConnection.Open(). Since all connections inherit from System.Data.IDbConnection (and, more importantly, they all look like IDbConnection), I can use that interface as the type I will be using for duck typing.

Wrap the Sealed Class Instance and Create the Duck

DynamicObject dynamic = new DynamicObject(new SqlConnection());

// Note that this action doesn't actually cast it to an IDbConnection;
// it just makes it *act* like one
IDbConnection duck = dynamic.CreateDuck<IDbConnection>();

Override the Duck

Next, we need to create an interceptor that wraps around the intended target method or methods. In this case, we want to wrap IDbConnection.Open():

public class CustomInterceptor : IInvokeWrapper
{
   private object _target;
   public class CustomInterceptor(object target)
   {
      _target = target;
   }
   public void BeforeInvoke(InvocationInfo info)
   {
      if (info.TargetMethod.Name != "Open")
          return;

      // Add the additional behavior here
      Console.WriteLine("Open Method Called!");
   }

    public object DoInvoke(InvocationInfo info)
    {
        // Call the original implementation
        object result = info.TargetMethod.Invoke(_target, info.Arguments);

        return result;
    }

    public void AfterInvoke(InvocationInfo info, object returnValue)
    {
        // Do nothing
    }
}

Once the interceptor has been defined, the next thing to do is create a proxy for IDbConnection. Then tie the duck and the CustomInterceptor together into one instance:

ProxyFactory factory = new ProxyFactory();
IDbConnection unsealed = 
    factory.CreateProxy<IDbConnection>(new CustomInterceptor(duck));

// Once the Open() method is called, it will now print "Open Method Called!"
unsealed.Open();

...and that's how you unseal a sealed type.

Interceptor by Design

For those of you who use LinFu's DynamicProxy, one thing that you might find interesting is that DynamicObjects are interceptors themselves. This means that any DynamicObject can act as an interceptor for any proxy created by LinFu.DynamicProxy's ProxyFactory class. For example, suppose that I already have an existing proxy in memory and I want to create a dynamic interceptor so that I can attach it to the proxy:

ProxyFactory factory = new ProxyFactory();
IMath math = factory.CreateProxy<IMath>();

// Create the dynamic interceptor
DynamicObject interceptor = new DynamicObject();

// Attach it to the proxy
IProxy proxy = math as IProxy;
proxy.Interceptor = interceptor;

// Now the proxy is pointing back to the DynamicObject;
// This is where you would start dynamically adding methods
// to that DynamicObject
...

This approach makes it easy to incrementally build an interceptor implementation as the application is running. The possibilities are endless.

Using DynamicObject with C# 3.0

Another realm of possibilities opens up once you combine the abilities of LinFu.DynamicObject with the upcoming language features of C# 3.0. Some of these possibilities are:

Mixins Using Anonymous Types

Now that C# 3.0 has support for anonymous types, dynamically creating throwaway interface implementations is easy. Using an anonymous type, I can easily provide an implementation for IPerson by using the following code:

DynamicObject dynamic = new DynamicObject();
dynamic.MixWith(new {Name="Me", Age=18});
IPerson person = dynamic.CreateDuck<IPerson>();

// Print the name and age
Console.WriteLine("Name = {0}", person.Name);
Console.WriteLine("Age = {0}", person.Age);

Shorter Anonymous Delegates with Lambda Expressions

While in some ways, being able to write shorter anonymous delegates using lambda expressions is no more than syntactic sugar, using lambda expressions with LinFu.DynamicObject (in my opinion) makes the code a bit easier to read. For example, using the previous example with the MathOperation type, I can rewrite it using lambda expressions so that it looks something like:

public delegate int MathOperation(int a, int b);

public class Program
{
   public static void Main()
   {
       // Define the method body
       MathOperation body = (a, b)=> { return a + b; };

       // Create an empty DynamicObject
       // that wraps around a System.Object
       DynamicObject dynamic = new DynamicObject();
       dynamic.AddMethod("Add", body);

       // This will return '2'
       int result = (int)dynamic.Methods["Add"](1, 1);
   }
}

Saving Space

At first, saving yourself from typing a few characters doesn't seem to be a marginal gain in efficiency, but what if the IMath class were defined as:

public interface IMath
{
   int Add(int a, int b);
   int Subtract(int a, int b);
   int Multiply(int a, int b);
   int Divide(int a, int b);
}

What was once one small declaration has turned itself into four and you have effectively increased the amount of items you have to type by 400%. What if you had to type even more than that? Suffice it to say, once you've gotten past ten repetitive anonymous delegate declarations, you'll be well past the point of tedium. For the sake of simplicity, however, let's stick to the four operations mentioned above.

The next thing that I have to do is redefine all of the operations performed by the IMath class:

MathOperation add = (a, b) => { return a + b; }
MathOperation subtract = (a, b) => { return a – b; };
MathOperation multiply = (a, b)=> { return a * b; };
// Divide by zero check omitted for brevity
MathOperation divide = (a, b)=> { return a / b; }; 

Once again, in DynamicObject, I have to add the new methods and implement the interface:

DynamicObject dynamic = new DynamicObject();
dynamic.AddMethod("Add", add);
dynamic.AddMethod("Subtract", subtract);
dynamic.AddMethod("Multiply", multiply);
dynamic.AddMethod("Divide", divide);

IMath math = dynamic.CreateDuck<IMath>();

// Perform all of the operations
Console.WriteLine(math.Add(1, 1));
Console.WriteLine(math.Subtract(1, 1));
Console.WriteLine(math.Multiply(1, 1));
Console.WriteLine(math.Divide(1, 1));

As you can see here, being able to use lambda expressions in place of full-length anonymous delegate declarations can save quite a lot of time and typing. As for the rest of the code above, well, if you've gone this far into the article, then everything I mentioned above is practically boilerplate. It's almost as if dynamically adding methods were nothing new, but I digress.

Parsing LINQ Expression Trees

With LINQ coming up on the horizon, LinFu.DynamicObject naturally makes for a near-perfect expression tree visitor. Here's a simple (and hypothetical) example of a visitor using DynamicObject:

public class ExampleVisitor
{
   ...
   public void DoVisit(Expression expression)
   {
      // Let the DynamicObject decide which method to call
      DynamicObject dynamic = new DynamicObject(this);
      dynamic.Methods["Visit"](expression);
   }
   public virtual void Visit(MethodCallExpression expression)
   {
      // Do something useful here
   }
   public virtual void Visit(BinaryExpression expression)
   {
      // Do something useful here
   }
   ...
}

In this example, I wrapped ExampleVisitor using the DynamicObject class and I let DynamicObject determine which overload of the Visit() method will handle the current LINQ Expression. Once the client code calls DoVisit(), DynamicObject will walk the tree, leaving you to do something useful with the expression metadata.

LinFu.Reflection Features Still on the Drawing Board

The Wish List

Now that you have LinFu in your hands, here is a list of things that I would love to implement, but frankly, I don't have enough time or expertise to effectively come up with a solution to. If you have any personal projects that are similar to what I'm doing here, it would certainly be a pleasure for me to compare notes with you on these subjects. Anyway, here's the list:

Anonymous Interfaces

One of the problems in using LinFu.DynamicObject is that, aside from using the LooksLike() method, there is currently no way to tell which methods and properties DynamicObject implements. It would be nice to be able to have DynamicObject dynamically generate some type information that would allow it to describe its current internal state. This is where the concept of anonymous interfaces comes in. I can have each DynamicObject generate a nameless type that describes its current interface. I can use these dynamically generated anonymous interfaces and compare them with each other and test them for equality. Until I can figure out how to do this, it is nearly impossible to compare two dynamic objects and determine if they share the same methods and properties.

Differential Interfaces

Have you ever wanted to take two classes, put them side by side, and see which properties and methods they have in common? For example, let's say that I wanted to compare an ASP.NET button control with a standard Windows Forms button control. I want to be able to immediately determine which members these two classes have in common so that I can dynamically generate an interface to use for duck typing, employing those common members as part of the newly generated interface. The difference here is that I want this information dynamically generated at runtime and in memory, instead of having something that's scrawled on scraps of paper or a whiteboard that I cannot use.

Type Coercion Using TypeConverters

The general idea here is to modify DynamicObject to be smart enough to figure out whether or not a given runtime argument is compatible with a method signature by checking to see if that argument has a value that is convertible to the target argument type. In other words, I want to make DynamicObject smart enough to convert strings to enums and vice versa, as well as be able to convert integers to their numeric values and vice versa.

Invoking Late-bound Generic Methods with Open Type Parameters

LinFu.DynamicObject works well with generic methods with closed (read: assigned) type parameters, but right now there's no way to invoke a method if the class has something like the following signature:

public class SomeClass
{
   public void DoSomething<T>()
   {
   }
}

In its current state of development, LinFu.DynamicObject cannot invoke the DoSomething<T>() method because there is currently no way to tell DynamicObject that I am looking for a method with an open generic type parameter and that I want to instantiate it using the type parameter that I'm assigning to it. This process is rather complicated and it will take me quite a while to figure out how to implement.

Coming Up in the Next Article

In Part III of this series, I'll show you how you can use LinFu.Delegates to define closures with lambda arguments. I'll also show you how to use the EventBinder class to handle any event, regardless of the delegate signature used by any particular event. Here's an example:

MathOperation add = delegate(int a, int b) { return a + b; };

// Note: this closure will only be evaluated
// once the Invoke() method is called
Closure doMath = new Closure(add, new Closure
    (add, new Closure(add, 12, 9), 11), Args.Lambda);

// What's the answer?
// It's 42, of course! :)
int result = (int) doMath.Invoke(20);

...and suppose I wanted to use EventBinder to bind to a Windows Forms Button.Click event:

Button button = new Button();
CustomDelegate handler = delegate { Console.WriteLine("Button Clicked!"); };
EventBinder.BindToEvent("Click", button, handler);

...and if I really wanted to get fancy, I could even use Closures with LinFu.DynamicObject:

// Derive a new closure from the Add() method that takes a single argument
// and adds '1' to it
Closure lazyMathOperation = new Closure
    (dynamic.Methods["Add"], 1, Args.Lambda);

// This will return '6'
int result = (int) lazyMathOperation.Invoke(5);

One Last Word Before the Next Article

Now that I'm effectively done discussing LinFu's dynamic language extensions, my challenge to you as a fellow developer is to take this language's features and make something useful out of it. While you find something to do with it, I'll be finishing the rest of Part III. Stay tuned!

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralSyntactic Sugar
pwhe23
11:32 29 Nov '09  
Here is some useful Syntactic Sugar I added on top of LinFu using extensions. Talk about terse code.

	
public static class Extensions {

public static T As<T>(this Object obj) where T : class {
var dynamic = new DynamicObject();
dynamic.MixWith(obj);
return dynamic.CreateDuck<T>();
}

public static DynamicObject Add<T>(this DynamicObject dynamic, string name, T arg) {
dynamic.AddMethod(name, arg as MulticastDelegate);
return dynamic;
}

}

var person = new { Name = "Me", Age = 18 }.As<IPerson>();

var math = new DynamicObject()
.Add<MathOperation>("Add", (a, b) => a + b)
.Add<MathOperation>("Subtract", (a, b) => a - b)
.Add<MathOperation>("Multiply", (a, b) => a * b)
.Add<MathOperation>("Divide", (a, b) => a / b)
.CreateDuck<IMath>();


GeneralRe: Syntactic Sugar
Philip Laureano
12:11 29 Nov '09  
That's amazing--I never thought of using LinFu that way. Thanks for the tip!

Regards,

Philip Laureano


QuestionRe: Syntactic Sugar
pwhe23
15:02 29 Nov '09  
I have played with your excellent library and I am wondering if I can use it to create a class I need. I want to create a generic list class that I can give an interface to and then add a list of objects that implement that interface (or using DynamicObject appear to implement the interface). Then I can access a Duck property that contains a DynamicObject Duck with the interface and when I call a method on that object it calls each of the list's objects in order. I could almost use your mixins but it only calls the first method found, not each one. Here is an example of how the class could be used:

class Program {
static void Main() {
var list = new DuckList<IWriter>();
list.Add(new Writer1());
//note Writer2 has correct method but doesn't implement IWriter
list.Add(new Writer2());
//Duck is property that returns T (IWriter) and when called,
//invokes each IWriter in it's internal list
list.Duck.Write("Hello World: {0}", 2.0);
//output "Write1: Hello World: 2.0"
//output "Write2: Hello World: 2.0"
}
}
public interface IWriter {
void Write(String message, params object[] args);
}
public class Writer1 : IWriter {
public void Write(string message, params object[] args) {
Console.WriteLine("Write1: " + message, args);
}
}
public class Writer2 {
public void Write(string message, params object[] args) {
Console.WriteLine("Write2: " + message, args);
}
}

AnswerRe: Syntactic Sugar
Philip Laureano
2:45 30 Nov '09  
It's been a while since I've dabbled with LinFu.DynamicObject, but from what I can remember, there were actually a few extensions that I added to it that allowed you to have a bunch of DynamicObject instances share a common 'DynamicType' prototype in such a way that adding or removing methods to and from that prototype causes all dependent dynamicobject instances to dynamically change their behavior to match that prototype. Is that what you were looking for?



AnswerRe: Syntactic Sugar
pwhe23
4:32 30 Nov '09  
I figured it out. Wow, great library!!

public class DuckList<T> where T : class {
private readonly List<DynamicObject> _list = new List<DynamicObject>();
private readonly T _duck;
public DuckList() {
var dynamic = new DynamicObject();
foreach (var mi in typeof(T).GetMethods()) {
dynamic.AddMethod(mi.Name, (args) => Callback(mi.Name, args), mi.ReturnType, mi.GetParameters().Select(p => p.ParameterType).ToArray());
}
_duck = dynamic.CreateDuck<T>();
}
public void Add(object obj) {
if (obj == null) return;
_list.Add(new DynamicObject(obj));
}
public T Duck {
get {
return _duck;
}
}
private object Callback(string name, Object[] args) {
foreach (var o in _list) {
o.Methods[name](args);
}
return null;
}
}

GeneralThis is so good [modified]
captainplanet0123
16:01 5 Jun '09  
Great stuff Loreano, you ought to be designing the next CLR Wink
I mean the dynamic stuff, we're still waiting Anders Hejlsberg to incorporate it in c# 4.0, which is really a few years late with regards to your implementation.

Heh, now that's I've given you the (deserving) kudos, let me plug my own brain in:
I say this with the outmost respect, the Mixin resolution of duplicates I believe to be slightly naive for the class of this library.

I'm sure you know, but here is how popular languages resolve such issues, very similar and in reference to C++'s "Diamond problem" of multiple inheritance:

* C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" (for example, "class B : virtual public A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual inheritance and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A.
* Common Lisp attempts to provide both reasonable default behavior and the ability to override it. By default, the method with the most specific argument classes is chosen; then in the order in which parent classes are named in the subclass definition. However, the programmer can override this, by giving a specific method resolution order or stating a rule for combining methods.
* Eiffel handles this situation by select and rename directives, where the ancestors' methods to use in a descendant are explicitly specified. This allows the methods of the base class to be shared between its descendants or to even give each of them a separate copy of the base class.
* Perl and Io handle this by specifying the inheritance classes as an ordered list. In the above ambiguity, class B and its ancestors would be checked before class C and its ancestors, so the method in A would be inherited through B.
* Python had to deal with this upon the introduction of new-style classes, all of which have a common ancestor, object. Python creates a list of the classes that would be searched in left-first depth-first order (D, B, A, C, A) and then removes all but the last occurrence of any repeated classes. Thus, the method resolution order is: D, B, C, A.
* Ruby resolves method names using a reverse-inclusion-order depth-first search of included modules, before eliminating all but the last occurrence of each module in the resulting list. So, the resolution order is: [D, C, A, B, A], which reduces down to [D, C, B, A]
* Scala resolves method names using a right-first depth-first search of extended 'traits', before eliminating all but the last occurrence of each module in the resulting list. So, the resolution order is: [D, C, A, B, A], which reduces down to [D, C, B, A]


You seem to have taken a slightly Larry-Page-like (Perl) approach.
I personally prefer Meyer's (as in Eiffel) solution; it's just very clean and unambiguous, arguably superior to Perl's approach too!

Since you have implemented DBC as well, it feels much more appropriate approach for LinFu.
My second best is the approach used by Bjarne (C++); it isn't too shabby either...

What can I say, it's your call, if you insist in keeping it, well, I have to amend my copy of your library Poke tongue as I will probably use it for quite a few of my future projects. Big Grin

Many thanks and well done!
And here's your 5 out of 5! Thumbs Up

NT

modified on Friday, June 5, 2009 9:07 PM

GeneralRe: This is so good
Philip Laureano
17:34 5 Jun '09  
Thanks for the kind words. (It's a good thing that you replied when you did since I'm in the process of designing LinFu's DynamicObject 2.0)

captainplanet0123 wrote:
I mean the dynamic stuff, we're still waiting Anders Hejlsberg to incorporate it in c# 4.0, which is really a few years late with regards to your implementation.


Why wait for Anders when you have something like this? Smile

captainplanet0123 wrote:
Heh, now that's I've given you the (deserving) kudos, let me plug my own brain in:
I say this with the outmost respect, the Mixin resolution of duplicates I believe to be slightly naive for the class of this library.


Actually, it is indeed a naive implementation given the amount of work it would take to support each "flavor" of resolving the Diamond Inheritance problem. If you can't satisfy everyone, then it's best to go with the simplest option and let them sort it out.

captainplanet0123 wrote:

* C++ by default follows each inheritance path separately, so a D object would actually contain two separate A objects, and uses of A's members have to be properly qualified. If the inheritance from A to B and the inheritance from A to C are both marked "virtual" (for example, "class B : virtual public A"), C++ takes special care to only create one A object, and uses of A's members work correctly. If virtual inheritance and nonvirtual inheritance are mixed, there is a single virtual A and a nonvirtual A for each nonvirtual inheritance path to A.
* Common Lisp attempts to provide both reasonable default behavior and the ability to override it. By default, the method with the most specific argument classes is chosen; then in the order in which parent classes are named in the subclass definition. However, the programmer can override this, by giving a specific method resolution order or stating a rule for combining methods.
* Eiffel handles this situation by select and rename directives, where the ancestors' methods to use in a descendant are explicitly specified. This allows the methods of the base class to be shared between its descendants or to even give each of them a separate copy of the base class.
* Perl and Io handle this by specifying the inheritance classes as an ordered list. In the above ambiguity, class B and its ancestors would be checked before class C and its ancestors, so the method in A would be inherited through B.
* Python had to deal with this upon the introduction of new-style classes, all of which have a common ancestor, object. Python creates a list of the classes that would be searched in left-first depth-first order (D, B, A, C, A) and then removes all but the last occurrence of any repeated classes. Thus, the method resolution order is: D, B, C, A.
* Ruby resolves method names using a reverse-inclusion-order depth-first search of included modules, before eliminating all but the last occurrence of each module in the resulting list. So, the resolution order is: [D, C, A, B, A], which reduces down to [D, C, B, A]
* Scala resolves method names using a right-first depth-first search of extended 'traits', before eliminating all but the last occurrence of each module in the resulting list. So, the resolution order is: [D, C, A, B, A], which reduces down to [D, C, B, A]


(Oh and btw, this is awesome. I will definitely keep these diamond resolution strategies handy once I start working on DynamicObject 2.0 Smile )


captainplanet0123 wrote:
What can I say, it's your call, if you insist in keeping it, well, I have to amend my copy of your library Poke tongue as I will probably use it for quite a few of my future projects.


Actually, I would be really interested in seeing how you modify it to support those different diamond resolution strategies, and I believe the LGPL forbids anyone from making local changes to their modified copy of LinFu without publishing it so let's see what you can do it. Smile

captainplanet0123 wrote:
Many thanks and well done!
And here's your 5 out of 5! Thumbs Up


Again, you have my thanks, and there's plenty more where that came from. Smile

Best Regards,

Philip Laureano

Do you know...LinFu?

GeneralReflection
jpbochi
10:17 24 Dec '08  
Hey,

I read all your article and I fell that I mus disagree with the wish list you put in the Reflection section.

Comparing an object to an interface is not the only way to see what it implements. .NET reflection is pretty boog for this. Suppose you want a function that receives an regular System.Object returns a list the methods' names. Using the Objects' GetType() function would solve your problem. Like this:

static IEnumerable ListMethodsNames(object obj)
{
return obj.GetType().GetMethods().Select(methodInfo => methodInfo.Name).ToArray();
}

Unfortunately, this would NOT work properly with an DynamicObject. The output is this:
op_Subtraction, op_Addition, get_Methods, get_Properties, get_Target, set_Target, AddMethod, AddMethod, MixWith, LooksLike, LooksLike, CreateDuck, CreateDuck, MethodMissing, CanHandle, Intercept, ToString, Equals, GetHashCode, GetType

I think what is really missing in the implementation od DynamicObject is an GetDynamicType() function that would return a System.Type. If GetType() was a virtual method, you could override it, but I don't think it would be a good idea. An separate GetDynamicType() function seems better to me.

System.Type is an abstract class, but I never inherited from it. There might be some problems overriding the non-virtual methods, but you always could create a duck for it Wink.

I know it could be a heavy to dynamically create a Type instance for a DynamicObject. One possible solution is to left the Type instance bound to the DynamicObject instance. So, when someone calls a GetMethods() function, you would dynamically query the methods that are currently in the DynamicObject. I'm already digressing about it. It certainly needs some extra thought. If you don't mind I think I could try to write this later.

and congratulations for your code

JP
GeneralRe: Reflection
Philip Laureano
13:58 24 Dec '08  
jpbochi wrote:
I think what is really missing in the implementation od DynamicObject is an GetDynamicType() function that would return a System.Type. If GetType() was a virtual method, you could override it, but I don't think it would be a good idea. An separate GetDynamicType() function seems better to me


Hi JP,

The only problem that I see with dynamically generating a custom type that describes a DynamicObject instance is the fact that you'd have to generate essentially the same type for two DynamicObject instances that have the same members, and that could get very complicated. Dynamically inheriting from System.Type is quite tricky, and even I wasn't able to pull it off despite whatever IL tricks I had up my sleeves.

From what I can tell, it looks like you want to extend DynamicObject to support prototyping so that two DynamicObject instances should be logically equivalent if they share the same (proto)type. In theory, it's very possible, but for now, I'll put this on my TODO list for v2.0. Right now, the development for DynamicObject v2.0 is on hold until I can figure out exactly how Microsoft is going to use the DLR and C# 4.0 to implement their own version of DynamicObject. There's a lot of functionality there that overlaps with LinFu, and I'll wait for things to settle down before I jump in to developing the next version of DynamicObject.

If you want to play around with it, you can always try implementing your own version of IMethodMissing and see if you get the type equivalency up and running. It's definitely worth a shot Smile

jpbochi wrote:

and congratulations for your code

JP


Thanks for the kind words, JP. There's plenty more code where that came from Smile

HTH!

Do you know...LinFu?

GeneralRe: Reflection
jpbochi
5:59 29 Dec '08  
I think you got me wrong. I wasn't talking about equivalence between dynamic types.

One problem that my idea would solve is the one that you pointed in this statement "[...] there is currently no way to tell which methods and properties DynamicObject implements". By providing a Type instance for a DynamicObject, one could list its methods and properties (or do whatever he/she needs with them). By the way, a System.Type is not 100% necessary. Another similar type would solve the problem as well, but that deserves another thread.

As for dynamic-type equivalence, I don't believe it's needed at all. The LooksLike() function works more like a partial-order relationship. Essentially, the problem you state in the "Anonymous Interfaces" session is that you can't compare two dynamic types using the LooksLike() function. From my point of view, I don't think you need an anonymous interface at all.

Usually, all one needs to be able to do is (1) inspecting whether a given object implements a method or not, and (2) invoke the method. Invoking methods is perfectly possible wiht your code. To inspect the methods (or properties, or custom attributes, or etc.) of an object, reflection is the way to go. DynamicObject has no reflection implemented, and that's what I was proposing to do.

By the way, I intend to read all your articles on LinFu. Maybe, I'll post some comments on the others too. Smile
Questionhi, i meet a problem [modified]
chengjing
4:15 23 Nov '07  
LinFu is greate, but when i write some samples, i meet a problem.
this is my code:
DynamicObject dobj = new DynamicObject(System.DateTime.Now);
Console.WriteLine(dobj.Methods["ToString"]("yyyy-MM-dd"));

throw TargetParameterCountException;

but when i call Console.WriteLine(dobj.Methods["ToString"]()) will ok

-- modified at 10:08 Friday 23rd November, 2007

i change class 'PredicateBuilder's code of Line 180:
if (_matchParameters && _parameterTypes.Count == 0) -->
if (_matchParameters && _parameterTypes.Count == 0 && !_matchRuntimeArguments)

it works fine
AnswerRe: hi, i meet a problem
Philip Laureano
6:50 23 Nov '07  
Hi cheng,

Thanks for pointing that out! I've already patched the version in SVN to reflect your changes. Thanks again!
GeneralDynamic Properties
Dewey
19:43 21 Nov '07  
You show how to create dyanmic methods, but dynamic properties do not seem to be supported, at least directly, is this true?

If dynamic properties are not supported, I suppose they could be simulated by creating getter and setter methods for some pseudo "myproperty".

I looked at C# 3.0 Anonymous Types, and they are really nice, but they are read only(at least in C#, I hear VB can set variables).

Please comment on the above, and thanks for the beautiful code.
GeneralRe: Dynamic Properties
Philip Laureano
4:03 22 Nov '07  
Dewey wrote:
You show how to create dyanmic methods, but dynamic properties do not seem to be supported, at least directly, is this true?


One dirty little secret that the CLR folks never told us is that every rewritable property can be implemented using a method signature like YourPropertyType get_YourPropertyName() for the getter and using a method signature like void set_YourPropertyName(YourPropertyType value) for setter method. With this in mind, all you have to do is dynamically generate those two methods with the DynamicObject and duck type it down to an interface with a signature similar to the following:


public interface ISample
{
YourPropertyType YourPropertyName { get; set; }
}


Once you've dynamically generated the getter and setter methods and casted it down to the ISample duck type, you can use the ISample.YourPropertyName property as if it were actually there. The DynamicObject is smart enough to infer the property get/set call, so you shouldn't have any problems.

If you need something more flexible, such as a late bound property accessor call, you could use the following shortcut to use a dynamically-generated property instead of a duck-typed method call:


DynamicObject dynamic = new DynamicObject(new SomeSample())

// call the getter
YourPropertyType value = (YourPropertyType) dynamic.Properties["YourPropertyName"];

// call the setter
dynamic.Properties["YourPropertyName"] = value;


If you prefer strong typing, then I'd recommend option #1. If you're looking for something even more dynamic, then I'd recommend option #2. Either way, dynamically generating your getter and setter methods should have the same effect, no matter which option you choose. I hope that helps!



GeneralRe: Dynamic Properties
Dewey
15:26 22 Nov '07  
Philip, you are AMAZING.

Thanks for the detailed solution, and option 2 is better for me, I need the flexibility.

Again, Thanks!
GeneralRe: Dynamic Properties
Philip Laureano
20:23 22 Nov '07  
Dewey wrote:
Philip, you are AMAZING.

Thanks for the detailed solution, and option 2 is better for me, I need the flexibility.

Again, Thanks!


You're welcome. Smile Oh, and as a bonus, you might want to try defining properties on an interface and having the DynamicObject duck type that one too. As it turns out, events defined on a target type are no different than methods with special names, so if you wanted to say...duck type an event source using an interface, you could do something like define dynamic events using the following hypothetical method signatures:



public void add_YourEventName(YourDelegateType handler);
public void remove_YourEventName(YourDelegateType handler);


What makes this interesting is that every time an object subscribes itself to the event fired by an interface instance that is handled by the DynamicObject, the DynamicObject actually passes that delegate instance back to your dynamically generated methods to bind to a handler. In effect, you not only have a universal event handler with LinFu--you can also have a Universal Event Source. Smile Think about it....




GeneralPart III
Philip Laureano
2:32 4 Nov '07  
You can read it by clicking here. Smile
QuestionAwesome. What about "un-sealed" operator overloading? Constrained generics? License?
dcuccia
23:08 31 Oct '07  
Wow, great work.

So, your interceptors allow you to "un-seal" a class (in some ways, at least)...

1) Can that somehow permit operator overloading in sealed classes (ie. like float[] + float[] )

2) What about generics constrained with sealed classes? (ie. T Add(T a, T b) where T : IFloat, IDouble, etc)

You may have already touched on 2) and I didn't even realize it.

Oh, under what license do you plan on releasing this SW?

Thanks!
David


AnswerRe: Awesome. What about "un-sealed" operator overloading? Constrained generics? License?
Philip Laureano
4:18 1 Nov '07  
dcuccia wrote:
Wow, great work.

So, your interceptors allow you to "un-seal" a class (in some ways, at least)...

1) Can that somehow permit operator overloading in sealed classes (ie. like float[] + float[] )

2) What about generics constrained with sealed classes? (ie. T Add(T a, T b) where T : IFloat, IDouble, etc)

You may have already touched on 2) and I didn't even realize it.

Oh, under what license do you plan on releasing this SW?

Thanks!
David


1) Unfortunately, I can't do anything about operator overloading since it all operator overloads in .NET are actually static methods that are called by the compiler, and since they're static, it doesn't really matter whether or not the class is sealed--there's no way to change an existing implementation.

2) I haven't played around with type constraints that much, but you might be able to get around type constraints if you dynamically subclass from the nearest unsealed common ancestor in the hierarchy and use the DynamicObject to do some duck typing and reuse the sealed implementation. Does this answer your question?

As for the license--it's LGPL, meaning that you can use the compiled DLL in your commercial applications without any royalties, but if you make any modifications to the source, you have to publish it so that everyone else can use it. Other then that, I really don't expect to get much money out of this--I'd just be happy if you tell everyone you know about LinFu Smile

HTH! Thanks.



GeneralSimply amazing
Pete O'Hanlon
1:47 31 Oct '07  
You've managed to implement features that I've just started to play around with in 3.0, and in some cases you've outperformed the new feature set. It would be interesting if MS got in touch with you and talked about you coming on board the team. You've certainly proved you've got the chops to satisfy them.

Deja View - the feeling that you've seen this post before.

GeneralRe: Simply amazing
Philip Laureano
2:46 31 Oct '07  
Thanks for the kind words, Pete. Smile

For me, it's quite fulfilling knowing that there are others like myself who enjoy digging into the internals of the CLR as a hobby, and it's even more rewarding to know that this hobby also (somehow) happens to be a profession. Right now, having MS contact me seems like a pipe dream, but a very nice dream, nonetheless. Smile



GeneralRe: Simply amazing
Pete O'Hanlon
11:37 31 Oct '07  
You've given me the impetus to try something that I was thinking of previously. I once wondered whether or not it would be possible to use an attribute to store a value in, which could be replaced at runtime. There are some cases where this could be quite useful, and I can see how this could be accomplished using what you've shown so far.

Deja View - the feeling that you've seen this post before.

GeneralRe: Simply amazing
Philip Laureano
13:12 31 Oct '07  
I tried it using the following code:

[AttributeUsage(AttributeTargets.Method)]
public class SomeMethodAttribute : Attribute
{
private int _value;
public int Value
{
get { return _value; }
set { _value = value; }
}
}

public class TestClass
{
[SomeMethod]
public void TestMethod()
{

}
}
class Program
{
static void Main()
{
MethodInfo method1 = typeof (TestClass).GetMethod("TestMethod");
MethodInfo method2 = typeof(TestClass).GetMethod("TestMethod");

// This returns true
bool sameReference = object.ReferenceEquals(method1, method2);

// Every time the method is reflected, a new
// SomeMethodAttribute is created
SomeMethodAttribute attr1 = (SomeMethodAttribute)method1.GetCustomAttributes(false)[0];
SomeMethodAttribute attr2 = (SomeMethodAttribute)method2.GetCustomAttributes(false)[0];

// Assign some values
attr1.Value = 1;
attr2.Value = 2;
// This returns false
sameReference = object.ReferenceEquals(attr1, attr2);

SomeMethodAttribute attr3 = (SomeMethodAttribute)method2.GetCustomAttributes(false)[0];

// This returns false
bool isSame = attr1 == attr2 && attr2 == attr3 && attr1.Value == attr3.Value;
return;
}
}


You can store values in attributes, but the moment you reflect on the same method (or type) again, you're going to get a completely new instance of that particular attribute. One way to work around it is to cache the attribute so that you always hit the same reference, but I'm not really sure how useful it would be.
GeneralRe: Simply amazing
Pete O'Hanlon
0:35 1 Nov '07  
Philip Laureano wrote:
You can store values in attributes, but the moment you reflect on the same method (or type) again, you're going to get a completely new instance of that particular attribute. One way to work around it is to cache the attribute so that you always hit the same reference, but I'm not really sure how useful it would be


You ran into exactly the same issue that I did when I coded it up originally. I'm wondering if it would be possible using your framework, to implement an interceptor on the reflection of the attribute so that it automatically returned you a cached reference. In pseudo-logic, what I was thinking of was:

Get the attribute using reflection
Read a value from the attribute (if the item has previously been reflected, read it from the cache otherwise write the value to a cache).
Update this value with another (again, this would update the cache).

As long as this was done using your framework, then the reflection code would not need to change. Hmm. I think I might just have to play around with this.

Deja View - the feeling that you've seen this post before.

GeneralRe: Simply amazing
Philip Laureano
4:09 1 Nov '07  
One way you might be able to go about this is if you rely on an interface to read/write the value from an attribute, and you can create a bunch of proxies using LinFu.DynamicProxy so that all of the proxy instances will always be pointing to the same cached attribute.

I'm not sure where you're going with this, but it does sound interesting. Smile


Last Updated 12 Nov 2007 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010