簡體   English   中英

C#字符串到對象而不使用反射

[英]C# String to Object without using Reflection

在C#中, 使用反射就可以基於字符串獲取對象的實例嗎?

例如:

Activator.CreateInstance(Type.GetType(objName));

使用反射。

是否可以將工廠類的經典if \\ else結構替換為不使用反射的“字符串到對象”實現?

我聽說那里有,但是我不明白你會怎么做而沒有反思。

有,但這不是一個簡單的解決方案。 本質上,您創建一個動態方法,然后從中創建一個委托並使用它。

public static BaseBuilder Create(Type builderType, HttpContextBase httpContext, PathDataDictionary pathData)
{
  if (!builderType.IsSubclassOf(baseBuilderType)) return null;

  BuilderConstructorDelegate del;
  if (builderConstructors.TryGetValue(builderType.FullName, out del))
    return del(httpContext, pathData);

  DynamicMethod dynamicMethod = new DynamicMethod("CreateBaseBuilderInstance", builderType, constructorMethodArgs, builderType);
  ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
  ilGenerator.Emit(OpCodes.Ldarg_0);
  ilGenerator.Emit(OpCodes.Ldarg_1);
  ilGenerator.Emit(OpCodes.Newobj, builderType.GetConstructor(constructorMethodArgs));
  ilGenerator.Emit(OpCodes.Ret);

  del = (BuilderConstructorDelegate)dynamicMethod.CreateDelegate(typeof(BuilderConstructorDelegate));
  builderConstructors.TryAdd(builderType.FullName, del);
  return del(httpContext, pathData);
}

這是我在用於ASP.NETBuilder中使用的一些代碼

BuilderFactory中的框架。

如果代碼中不清楚,則應該知道,一旦有了委托,則該刪除將存儲在上述代碼中名為builderConstructors的字典中。 因此,下次工廠僅使用委托時。

在這種特殊情況下,該類在其構造函數中需要兩個參數。 如果您對類使用默認的構造函數,則事情會更簡單一些。

高性能班級工廠

由於您在問題中使用了依賴注入標簽,因此依賴注入框架通常會為您完成此操作。 總是涉及反射,但是其中大多數將具有緩存機制,該機制可防止在下次請求對象時進行任何反射。 特別是當您的類型是具有默認構造函數的具體類型時(如您的問題所示),則不需要注冊。 例如,當使用簡單服務定位器時 ,請求將如下所示:

object instance = ServiceLocator.Current.GetInstance(Type.GetType(objName));

當您不想使用依賴項注入框架時,您可以做的是生成用於創建這些對象的委托,並將它們緩存在以objName作為鍵的字典中(這基本上就是DI框架所要做的)。 雖然您可以使用LCG(如Shiv所示),但新的.NET 3.5 Expression樹使其變得更加容易:

private static Dictionary<string, Func<object>> delegates = 
    new Dictionary<string, Func<object>>();

public static object CreateObjectByName(string name)
{
    if (delegates.ContainsKey(name))
    {
        return delegates[name]();
    }
    else
    {
        Func<object> creator = CreateDelegateFor(Type.GetType(name));

        // TODO: Don't forget to make this thread-safe :-)
        delegates[name] = creator;
    }
}

// .NET Expression tree magic!
private static Func<object> CreateDelegateFor(Type type)
{
    var constructor = type.GetConstructors().First();

    var newServiceTypeMethod = Expression.Lambda<Func<object>>(
        Expression.New(constructor, new Expression[0]), 
        new ParameterExpression[0]);

    return newServiceTypeMethod.Compile();
}

您可以使用Microsoft.VisualBasic.Interaction.CreateObject ,但這僅適用於COM對象。 (從好的方面來說,這使您可以在其他人的計算機上創建對象。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM