Friday, August 21, 2009

Xaf tip # 4

This is my 4th post on my Xaf tips series

Runtime Member creation on TypesInfo and XPDictionary

When you are developing modules and need to generate runtime member you should be carefull which method you choose because the following is valid always

Assert.IsNull(XafTypesInfo.Instance.FindTypeInfo(typeof(Country)).CreateMember("TestMember", typeof(string)));

and this one not

Assert.IsNull(XafTypesInfo.XpoTypeInfoSource.XPDictionary.GetClassInfo(typeof(Country)).CreateMember("TestMember",typeof(string)));

So to test my sayings create a new Xaf Application add a controller and call

public override void CustomizeTypesInfo(ITypesInfo typesInfo){
    base.CustomizeTypesInfo(typesInfo);
    var memberInfo = XafTypesInfo.XpoTypeInfoSource.XPDictionary.GetClassInfo(typeof(Country)).CreateMember("TestMember",typeof(string));
}
memberInfo  in this case is not null

but when

public override void CustomizeTypesInfo(ITypesInfo typesInfo){
    base.CustomizeTypesInfo(typesInfo); 
    var memberInfo = XafTypesInfo.Instance.FindTypeInfo(typeof(Country)).CreateMember("NewProperty", typeof(String));

memberinfo is null!!! It is going to work only if you add Country to your AdditionalBusinessClasses collection

like

image

Did you know that?

So typesInfo knows only about your application BussinessClass and XPDictionary about any persistent class

Which one to use ? I would suggest the XPDictionary one cause XPDictionary can also add runtime non persistent member like collections .

I have also write a small helper class to help me add a runtime association with less code

public static class TypesInfoExtensions{
    public static bool CreateCollection(this ITypesInfo typeInfo, Type typeToCreateOn, Type typeOfCollection,
                                        string associationName, XPDictionary dictionary){
        if (typeIsRegister(typeInfo, typeToCreateOn)){
            XPClassInfo xpClassInfo = dictionary.GetClassInfo(typeToCreateOn);
            XPCustomMemberInfo member = xpClassInfo.CreateMember(typeOfCollection.Name + "s", typeof (XPCollection),
                                                                 true);
            member.AddAttribute(new AssociationAttribute(associationName, typeOfCollection));
            return true;
        }
        return false;
    }

    private static bool typeIsRegister(ITypesInfo typeInfo, Type typeToCreateOn){
        return typeInfo.PersistentTypes.Where(info => info.Type == typeToCreateOn).FirstOrDefault() != null;
    }

    public static bool CreateBothPartMembers(this ITypesInfo typesInfo, Type typeToCreateOn, Type otherPartType,
                                             XPDictionary dictionary){
        return CreateBothPartMembers(typesInfo, typeToCreateOn, otherPartType, Guid.NewGuid().ToString(), dictionary);
    }

    public static bool CreateBothPartMembers(this ITypesInfo typesInfo, Type otherPartType, Type typeOfMember,
                                             string associationName, XPDictionary dictionary){
        bool members = CreateMember(typesInfo, otherPartType, typeOfMember, associationName,dictionary);
        if (members)
            members = CreateCollection(typesInfo, typeOfMember, otherPartType, associationName, dictionary);
        return members;
    }

    public static bool CreateMember(this ITypesInfo typesInfo, Type typeToCreateOn, Type typeOfMember,
                                    string associationName,XPDictionary dictionary){
        if (typeIsRegister(typesInfo, typeToCreateOn)){
            XPClassInfo xpClassInfo = dictionary.GetClassInfo(typeToCreateOn);
            XPCustomMemberInfo member = xpClassInfo.CreateMember(typeOfMember.Name, typeOfMember);
            member.AddAttribute(new AssociationAttribute(associationName));
            return true;
        }
        return false;
    }

    public static bool CreateBothPartMembers(this ITypesInfo typesinfo, Type typeToCreateOn, Type otherPartMember, XPDictionary xpDictionary, bool isManyToMany, string association){

        bool collection = CreateCollection(typesinfo, typeToCreateOn, otherPartMember, association, xpDictionary);
        if (collection)
            collection = CreateCollection(typesinfo, otherPartMember, typeToCreateOn, association, xpDictionary);
        return collection;
    }

    public static bool CreateBothPartMembers(this ITypesInfo typesinfo, Type typeToCreateOn, Type otherPartMember, XPDictionary xpDictionary, bool isManyToMany){
        Guid guid = Guid.NewGuid();
        return CreateBothPartMembers(typesinfo, typeToCreateOn, otherPartMember, xpDictionary,isManyToMany,guid.ToString());
    }
}

so now you can create a many to many association between your Country and Customer classes with code like

XafTypesInfo.Instance.CreateBothPartMembers(typeof (Customer), typeof(Country),
XafTypesInfo.XpoTypeInfoSource.XPDictionary, true);

one note here the 3rd parameter could be removed if Devexpress implements this suggestion

so the above code could be written like

XafTypesInfo.Instance.CreateBothPartMembers(typeof (Customer), typeof(Country), true);

ps:You may wonder why i use the typeIsRegister method on my extensions for the answer my friends read this Xaf tip #2

Technorati Tags: ,,

Subscribe to XAF feed
Subscribe to community feed

DiggIt!

2 comments:

  1. Hi great posts.. Do you have larger versions of the videos in your Expand posts?

    ReplyDelete
  2. Hi Ali thnks for your comments. Since I am getting many complains about video quality I am going to improve it a lot in the next posts and if I have time re publish the top of them

    ReplyDelete