Click here to Skip to main content
15,881,682 members
Articles / Programming Languages / XML

LinFu.DynamicModel, MxClone, and the Art of Adaptive Object Models

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
21 Jan 2018LGPL33 min read 4.8K  
LinFu.DynamicModel, MxClone, and the art of Adaptive Object Models

I've done it! :) Both the LinFu.DynamicModel and the MxClone (the MyXaml Engine Clone) libraries are ready for production use, and I can't wait to get started on writing the CodeProject articles for both libraries.

A Tale of Two Approaches

As I mentioned in the previous posts, LinFu.DynamicModel allows you to dynamically create an entire object model in memory at runtime without having to recompile your application. With LinFu.DynamicModel, you can either construct the model directly through code, or you can use the MxClone to create the model for you, using XML markup. I'll briefly go over each approach in the following sections, but before I do that, let's take a look at the interface implementation that we're going to dynamically generate.

A Canonical Approach: The Person Interface

Let's suppose that I wanted to dynamically create a dynamic type that looks like the following interface:

C#
public interface IPerson
{
   int Age { get; set; }
   string Name { get; set; }
}

Using LinFu.DynamicModel in Your Code

Here's how you can dynamically create a type that implements the IPerson interface:

C#
// TypeSpec objects are type descriptions that can be modified at runtime
TypeSpec personSpec = new TypeSpec()
{
   Name="PersonType",
 
   // Notice the strongly-typed properties
   Properties =
   {
       new Property<int>("Age"),
       new Property<string>("Name")
   },
};

// This will return true
bool isPerson = personSpec.LooksLike<IPerson>();
var person = personSpec.CreateDuck<IPerson>();

// Use the person object just like any other POCO
person.Age = 18;
person.Name = "Me";
// ...

Thanks to C#'s 3.0 new language features, you can easily create a model in memory with LinFu in relatively few lines of code. What makes this particularly interesting, however, is the fact that as the given TypeSpec changes, all of the IPerson instances that rely on that TypeSpec automatically "change" their behavior to match the newly-modified Person TypeSpec.

Using LinFu.DynamicModel with MxClone

Needless to say, there's a myriad of things you can do with this sort of technology, but it gets better--you can describe the same model through XML, using a MyXaml-style syntax:

XML
<?xml version="1.0" encoding="utf-8"?>
<Root xmlns="LinFu.Reflection.Extensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
xmlns:def="Definition"  xmlns:set="Setters">
  <TypeSpec def:Name="PersonType" Name="PersonType">
    <Properties>
      <PropertySpec PropertyName="Name"
                    PropertyType="System.String">
        <set:Behavior>
          <PropertyBag/>
        </set:Behavior>
      </PropertySpec>     
      <PropertySpec PropertyName="Age"
                    PropertyType="System.Int32">
        <set:Behavior>
          <PropertyBag/>
        </set:Behavior>
      </PropertySpec>
     
    </Properties>
  </TypeSpec>

</Root>

As you can see, the XML syntax for MxClone is similar to MyXaml, with the exception of the set:Behavior element. MxClone allows you to assign object references to properties without having to give it a specific reference name (e.g., {SomeName}), and in this case, the set:Behavior element means that I'm assigning an object reference of type 'PropertyBag' to a property named "Behavior" on the PropertySpec type. (The PropertyBag class, in turn, is responsible for maintaining the state of each property on every given type instance -- but for now, I'll save that for the upcoming LinFu article on CodeProject).

In essence, MxClone is actually constructing the same TypeSpec in memory using XML markup. Having the model specified in XML allows you to change it at runtime without recompiling the application, and that could come in handy if you need to change your business model with minimal downtime. Anyway, back to the markup...

From XML to TypeSpec, in 15 Lines of Code

Now that we have the XML markup, the next thing you might be wondering about is the client code: exactly how do you convert that markup into a running TypeSpec? Here's how you do it:

C#
// Load the engine into the container
string directory = AppDomain.CurrentDomain.BaseDirectory;
SimpleContainer container = new SimpleContainer();
Loader loader = new Loader(container);
loader.LoadDirectory(directory, "*.dll");

IMxEngine engine = container.GetService<IMxEngine>();

// The instance holder will 
// store the object graph once
// it's been instantiated by the engine
IInstanceHolder holder = new DefaultInstanceHolder();
string file = @"C:\YourDirectory\SimpleTypeSpecSample.xml";
engine.Execute(file, holder);

TypeSpec spec = holder.GetInstance<TypeSpec>("PersonType");
bool isPerson = spec.LooksLike<IPerson>();

// Use the person class normally
IPerson person = spec.CreateDuck<IPerson>();
person.Age = 18;
person.Name = "Me";

In the example above, I used the Simple.IOC container to instantiate the MxClone Engine. The engine, in turn, converted the XML markup into a working Person TypeSpec, and lastly, I used that same TypeSpec instance to create the IPerson instance. It's just that simple. :)

Conclusion

As you can see, there's quite a bit of development going on with LinFu.DynamicModel and LinFu.MxClone, and like everything else in the LinFu project, it will all remain under the LGPL license. I've put my heart and soul into this project, and hopefully, everyone will see that once the next set of LinFu articles comes out on CodeProject. Stay tuned!

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior) Readify
Australia Australia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --