开发者

How to dynamically extend C# class with new methods

I'm building a website in ASP.NET that allows creating new modules based on a common class. The new modules need to have the ability to extend the base class with their own library of methods/functions. I would like to load all modules at Application_Start. They are identified by a unique string key.

The structure is something like this:

root

-Bin
--module1.dll    
--module2.dll

-Modules
--module1
---mod.key1
--module2
---mod.key2

At startup each module folder is read and it's key identified, all settings loaded from db and common properties set, then stored in a collection. When a page is requested for a module, the base page class loads the appropriate module using it's unique directory key. Problem is the base module class does not contain the library of methods specific to that module (Only it's properties/settings loaded from db). How can I extend the module class to include methods during the module load at startup, or just instantiate the correct extended class d开发者_运维技巧ynamically using it's string name? or any other ideas? I don't want to hard code class names in the app load method so it can scale for future modules to be added.


There are several ways to do that. One way is to create a base class or interface from which to inherit, write your descendant classes in another DLL, and then use the Assembly.LoadFrom() method to load the appropriate classes from the DLL, as needed.

public MyType LoadTypeFromAssembly(string assemblyPath, string typeName)
{
            var assembly = Assembly.LoadFrom(assemblyPath);

            if (assembly == null)
                throw new InvalidOperationException("Could not load the specified assembly '" + assemblyPath + "'");

            var type = assembly.GetType(typeName);
            if (type == null)
                throw new InvalidOperationException("The specified class '" + typeName + "' was not found in assembly '" + assemblyPath  + "'");

            var instance = (MyType)Activator.CreateInstance(type);
            return instance;
}

Where MyType is the type of your base class or interface, and typeName is the name of your descendant class (that inherits from MyType).


This might can help u , I am having a model as @Robert saying .

I have to switch to my business layer depending on the entry in the database .

If there is a entry for a custom business layer dll in database i have to load from the path specified in the database table for the custom assembly or else i have to load the class from default business layer in my websites bin folder.

namespace BO.Factory
    {
        public class CFactory
        {

            public static object getClassInstance(string key, params  object[] constructorArgs)
            {
                try
                {
                    string assemblyPath = null;
                    string customClassName = null;
                    DataSet objDataset = getAssemblyInfo(key);
                    if (objDataset != null && objDataset.Tables.Count > 0 && objDataset.Tables[0].Rows.Count > 0)
                    {
                        assemblyPath = objDataset.Tables[0].Rows[0]["ACA_ASSEMBLY_PATH"].ToString();
                        customClassName = objDataset.Tables[0].Rows[0]["ACA_CLASS_NAME"].ToString();
                    }

                    Assembly assembly;
                    Type type;
                    string className;

                    if (assemblyPath != null && assemblyPath != string.Empty)
                    {
                        assembly = Assembly.LoadFile(assemblyPath);
                        className = customClassName;
                    }
                    else // if no customisation
                    {
                        assembly = key.Split('.')[1].ToString() == "BO" ? typeof(Catalyst.BO.SchoolBO.CSchoolBO).Assembly : typeof(Catalyst.DAL.SchoolDAO.CSchoolDAO).Assembly;
                        className = key;
                    }

                    type = assembly.GetType(className, true, true);

                    object classInstance = constructorArgs == null ? Activator.CreateInstance(type) : Activator.CreateInstance(type, constructorArgs);
                    if (classInstance == null) throw new Exception("broke");
                    return classInstance;
                }
                catch (Exception e)
                {
                    throw (e);
                }

            }

            static DataSet getAssemblyInfo(string key)
            {
                try
                {
                    string cmdText = "SELECT ACA_ID,ACA_KEY,ACA_ASSEMBLY_PATH,ACA_CLASS_NAME "
                                    + "FROM ADM_CUSTOM_ASSEMBLY_INFO "
                                    + "WHERE ACA_KEY='" + key + "'";

                    System.Data.SqlClient.SqlCommand sqlcommand = new System.Data.SqlClient.SqlCommand(cmdText);

                    DAL.DBHelper.CDBHelper objCDBHelper = new Catalyst.DAL.DBHelper.CDBHelper();

                    return objCDBHelper.PopulateDS(sqlcommand);
                }
                catch
                {
                    return null;
                }

            }
        }
    }

Both my default class and custom class inherit from a common interface which as all common methods defined in it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜