posts - 165,  comments - 876,  trackbacks - 42

经常用反射创建对象的朋友一定用过Activator.CreateInstance方法,这段时间在学习IL用Emit也实现了这样一个功能,也支持多不同参数的构造。
不过动太方法的key构造并不理想所以在性能上有所损耗,但其性能还是优胜于Activator.CreateInstance方法。
以下是测试代码和工厂代码

    public delegate object CreateInstanceHandler(object[] parameters);
    
public class Program
    
{
        
public Program()
        
{
        }

        
public Program(int i)
        
{
        }

        
public Program(int i, string name)
        
{
        }

        
static void Main(string[] args)
        
{

            Program p;
            p 
= Activator.CreateInstance<Program>();
            p 
= CreateObjectFactory.CreateInstance<Program>();
            p 
= (Program)Activator.CreateInstance(typeof(Program), new object[] 2 });
            p 
= CreateObjectFactory.CreateInstance<Program>(new object[] 2 });
            p 
= (Program)Activator.CreateInstance(typeof(Program), new object[] 2"henry" });
            p 
= CreateObjectFactory.CreateInstance<Program>(new object[] 2"henry" });
            System.Diagnostics.Stopwatch sw 
= new System.Diagnostics.Stopwatch();
            
for (int i = 0; i < 10; i++)
            
{
                sw.Reset();
                sw.Start();
                p 
= Activator.CreateInstance<Program>();
                p 
= (Program)Activator.CreateInstance(typeof(Program), new object[] 2 });
                p 
= (Program)Activator.CreateInstance(typeof(Program), new object[] 2"henry" });
                sw.Stop();
                Console.WriteLine(
"Reflection:\t" + sw.Elapsed.TotalMilliseconds);

                sw.Reset();
                sw.Start();
                p 
= CreateObjectFactory.CreateInstance<Program>();
                p 
= CreateObjectFactory.CreateInstance<Program>(new object[] 2 });
                p 
= CreateObjectFactory.CreateInstance<Program>(new object[] 2"henry" });
                sw.Stop();
                Console.WriteLine(
"Emit:\t" + sw.Elapsed.TotalMilliseconds);

            }

            Console.Read();
        }

    }

    
public class CreateObjectFactory
    
{
        
public static T CreateInstance<T>()
        
{
            
return CreateInstance<T>(null);
        }

        
static Dictionary<string, CreateInstanceHandler> mHandlers = new Dictionary<string, CreateInstanceHandler>();

        
public static T CreateInstance<T>(params object[] parameters)
        
{
            Type objtype 
= typeof(T);
            Type[] ptypes 
= GetParameterTypes(parameters);
            
string key = typeof(T).FullName + "_" + GetKey(ptypes);
            
if (!mHandlers.ContainsKey(key))
            
{
                CreateHandler(objtype, key, ptypes);
            }

            
return (T)mHandlers[key](parameters);

        }

        
static void CreateHandler(Type objtype, string key, Type[] ptypes)
        
{
            
lock (typeof(CreateObjectFactory))
            
{
                
if (!mHandlers.ContainsKey(key))
                
{
                    DynamicMethod dm 
= new DynamicMethod(key, typeof(object), new Type[] typeof(object[]) }typeof(CreateObjectFactory).Module);
                    ILGenerator il 
= dm.GetILGenerator();
                    ConstructorInfo cons 
= objtype.GetConstructor(ptypes);

                    il.Emit(OpCodes.Nop);
                    
for (int i = 0; i < ptypes.Length; i++)
                    
{
                        il.Emit(OpCodes.Ldarg_0);
                        il.Emit(OpCodes.Ldc_I4, i);
                        il.Emit(OpCodes.Ldelem_Ref);
                        
if (ptypes[i].IsValueType)
                        
{
                            il.Emit(OpCodes.Unbox_Any, ptypes[i]);
                        }

                        
else
                        
{
                            il.Emit(OpCodes.Castclass, ptypes[i]);
                        }



                    }

                    il.Emit(OpCodes.Newobj, cons);
                    il.Emit(OpCodes.Ret);
                    CreateInstanceHandler ci 
= (CreateInstanceHandler)dm.CreateDelegate(typeof(CreateInstanceHandler));
                    mHandlers.Add(key, ci);

                }

            }

        }

        
static Type[] GetParameterTypes(params object[] parameters)
        
{
            
if (parameters == null)
                
return new Type[0];
            Type[] values 
= new Type[parameters.Length];
            
for (int i = 0; i < parameters.Length; i++)
            
{
                values[i] 
= parameters[i].GetType();
            }

            
return values;
        }

        
static string GetKey(params Type[] types)
        
{
            
if (types == null || types.Length == 0)
                
return "null";
            
return string.Concat(types);
        }


    }
posted on 2008-05-23 21:17 henry 阅读(1205) 评论(4)  编辑 收藏 所属分类: Emit

FeedBack:
2008-05-23 21:26 | 簡簡單單..      
封装较差..
  回复  引用  查看    
#2楼 [楼主]
2008-05-23 21:35 | henry      
@簡簡單單..
就是几个静态方法,真的不知道如何封装,请教请教
  回复  引用  查看    
2008-05-24 11:07 | zzf [未注册用户]
封装的还行吧,思路不错……
  回复  引用    
2008-05-24 15:30 | HedgeHog      
博主,能问个问题不?

我 动态创建一个类 , 想把它保存到磁盘上时, 也就是 调用 AssemblyBuilder的Save()方法时,系统总是报 System.IO.IOException: 拒绝访问。 (异常来自 HRESULT:0x80070005 (E_ACCESSDENIED))

下面是代码:

AssemblyName name = new AssemblyName();
name.Name = "Result";

AssemblyBuilder asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.ReflectionOnly);

ConstructorInfo asmVersionCtor = typeof(AssemblyVersionAttribute).GetConstructor(new Type[] { typeof(string) });

CustomAttributeBuilder attrBuilder = new CustomAttributeBuilder(asmVersionCtor, new object[] { "2.2" });

asmBuilder.SetCustomAttribute(attrBuilder);

asmBuilder.Save("Result.DLL");


博主 或是 哪位路过的大哥能帮小弟看看的 ?我想实现一个读取XML文件的配置节,动态生成类内的属性. 谢谢了
  回复  引用  查看    

标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接:

 




<2008年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

寻求伯乐,限广州地区有意联系


与我联系

搜索

 

常用链接

留言簿(20)

我参加的小组

我的标签

随笔分类

最新评论

  • 1. re: JQuery实现自定义对话框
  • 你好 我是出版社的编辑,我看到你博客中的内容,感觉写的非常好,如果想把这些内容和更多的人分享,可以和我联系,把这些东西写成书。 我的邮箱:books_522008@yahoo.com.cn ...
  • --庞永庆
  • 2. re: 如何设计业务逻辑?
  • 我赞成定义,这需要丰富的应用经验。 --引用-------------------------------------------------- Ivony...: --引用------------...
  • --Kai.Ma
  • 3. re: 如何设计业务逻辑?
  • 针对LZ提出的,我们如何知道做出来的东西能满足以后的需要呢? 我自己的感觉,在满足自己目前的前提下,留一些适当的余地。 当有新的需求提出,重新检查下有无类似的代码? 如果有,而且发现重写一个新的方...
  • --思考-总结
  • 4. re: 如何设计业务逻辑?
  • 学习了

    第一种,要调整参数,感觉改起来麻烦
    第二种,感觉好很多
  • --未公布
  • 5. re: 如何设计业务逻辑?
  • 看文章,看评论,颇多收获!
  • --水言木

60天内阅读排行