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:
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:
TypeSpec personSpec = new TypeSpec()
{
Name="PersonType",
Properties =
{
new Property<int>("Age"),
new Property<string>("Name")
},
};
bool isPerson = personSpec.LooksLike<IPerson>();
var person = personSpec.CreateDuck<IPerson>();
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:
="1.0"="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:
string directory = AppDomain.CurrentDomain.BaseDirectory;
SimpleContainer container = new SimpleContainer();
Loader loader = new Loader(container);
loader.LoadDirectory(directory, "*.dll");
IMxEngine engine = container.GetService<IMxEngine>();
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>();
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!
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.