[英]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);
}
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.