Generically instantiate an entity

Posts   
 
    
thomas
User
Posts: 24
Joined: 21-Oct-2004
# Posted on: 02-Dec-2004 01:25:52   

I would like to instantiate various entities at runtime based on knowing the entity name. This is what I've got so far

 private object CreateEntityByName(string PartialAssemblyName, string EntityName) 
        { 
            return Activator.CreateInstance(Assembly.LoadWithPartialName(PartialAssemblyName).GetType(EntityName)); 
        }

The part that has me scratching my head is the actual definition. If the entity were a control on a form I could do something like this

 Control c = ((Control)CreateEntityByName("System.Windows.Forms", "System.Windows.Forms.Button")); 
c.Location = new Point(10, 10); 
c.Size = new Size(80, 26); 
c.Text = "Hello World"; 
this.Controls.Add(c);

Notice how the type being created is "Control"? So what would be the equivalent for LLBLGen UserEntities? Is EntityBase the appropriate type? Another way might be to just make it an "object" knowing that the "object" is always an Entity of some sort and therefore contains all methods and properties of a typical entity...

Hope this description made some sense.

Thanks, Thomas

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 02-Dec-2004 04:42:51   

You might find this entity factory appealing.

Here is the factory


public class CmsEntityFactory
{
    private CmsEntityFactory()
    {
    }

    //the factory method
    public static IEntity2 GetEntity(string entityName, params object[] args)
    {
        string assemblyName = "EDS.DNN.CMS, Version=0.11.2004.0, Culture=neutral, PublicKeyToken=null";
        string rootNameSpace = "EDS.DNN.CMS.EntityClasses.";

        Assembly asm = Assembly.Load(assemblyName);
        return (IEntity2)asm.CreateInstance(String.Concat(rootNameSpace, entityName), 
            true, BindingFlags.Default, null, args, null, null);
    }

    //method to fetch referenced assembly names
    public static void GetReferencedAssemblyNames()
    {
        Assembly asm = Assembly.GetExecutingAssembly();
        AssemblyName[] names = asm.GetReferencedAssemblies();
        for (int i = 0; i < names.Length; i++)
        {
            Console.WriteLine(names[i].FullName);
        }
    }
}

** Here are some unit tests**


[TestFixture()]
public class UnitTests
{
    public UnitTests()
    {
    }

    [Test]
    public void GetNewEntity()
    {
        CmsContentEntity myContentEntity = CmsEntityFactory.GetEntity("CmsContentEntity", null) as CmsContentEntity;
        Assert.IsNotNull(myContentEntity, "myContentEntity is null");
    }

    [Test]
    public void GetNewEntityById()
    {
        CmsContentEntity myContentEntity = CmsEntityFactory.GetEntity("CmsContentEntity", new object[]{123}) as CmsContentEntity;
        Assert.IsNotNull(myContentEntity, "myContentEntity is null");
    }

    [Test]
    public void GetNewEntityWithValidator()
    {
        CmsContentValidator validator = new CmsContentValidator();
        CmsContentEntity myContentEntity = CmsEntityFactory.GetEntity("CmsContentEntity", 
            new object[]{123,validator}) as CmsContentEntity;
        Assert.IsNotNull(myContentEntity, "myContentEntity is null");
    }

    [Test]
    public void GetReferencedAssemblyNames()
    {
        CmsEntityFactory.GetReferencedAssemblyNames();
    }

}

Hope they help. The thing to notice is that the Factory returns IEntity2 and uses reflection to create an instance of the entity. When it comes out of the factory as IEntity 2, I cast it to CmsContentEntity. If the object returned isnt a CmsContentEntity, then the assertion would fail. If the assertion wasnt there, you could check to see what kind of entity it really is.

EDIT This might explain it better:


    [Test]
    public void GetNewEntityWithValidator()
    {
        // get an entity using the factory
        IValidator validator = new CmsContentNotesValidator();
        IEntity2 myEntity = CmsEntityFactory.GetEntity("CmsContentNotesEntity", 
            new object[]{456,validator});
        Console.WriteLine(myEntity.GetType().Name);
        Console.WriteLine((myEntity as CmsContentNotesEntity).NoteID.ToString());

        // get another entity using the same objects
        validator = new CmsContentValidator();
        myEntity = CmsEntityFactory.GetEntity("CmsContentEntity", new object[]
            {123,validator});
        Console.WriteLine(myEntity.GetType().Name);
        Console.WriteLine((myEntity as CmsContentEntity).ContentID.ToString());
    }

jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 02-Dec-2004 07:32:58   

Hmmm...wouldn't the native GeneralEntityFactory work here?


Dim entity as IEntity2
entity = LLBL.FactoryClasses.GeneralEntityFactory.Create(System.Enum.ToObject(GetType(EntityType), "EmployeeEntity"))

There isn't one provided in Adapter, so I converted the Self-Servicing version. I can provide the template if desired, but it took me all of 3 seconds to do it...

Jeff...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 02-Dec-2004 10:41:59   

Thanks for the great answers, guys! simple_smile

Frans Bouma | Lead developer LLBLGen Pro
thomas
User
Posts: 24
Joined: 21-Oct-2004
# Posted on: 02-Dec-2004 21:18:35   

Thanks for both of the suggestions. Much appreciated! Devildog - I will try the built in approach first and if that doesn't get me where I want to be I will definetly look at the EntityFactory you listed. Super !

Thanks all. Thomas