C # String to Object без использования Reflection - PullRequest
1 голос
/ 12 ноября 2010

В C # возможно ли получить экземпляр объекта на основе строки без , используя Reflection?

Например:

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

использует отражение.

Можно ли заменить классическую структуру if \ else класса фабрики реализацией "строка-объект", в которой не используется отражение?

Я слышал, что есть,но я не понимаю, как бы вы сделали это без размышлений.

Ответы [ 3 ]

4 голосов
/ 12 ноября 2010

Есть, но это не простое решение. По сути, вы создаете динамический метод, а затем создаете из него делегата и используете его.

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);
}

Вот код, который я использую в Builder для ASP.NET

рамки в BuilderFactory.

Если в коде непонятно, вы должны знать, что после того, как у вас есть делегат, это удаление сохраняется в словаре с именем builderConstructors в приведенном выше коде. Поэтому в следующий раз фабрика просто использует делегата.

В этом конкретном случае классу требуется два параметра в своем конструкторе. Если вы используете конструктор по умолчанию для ваших классов, все немного проще.

Фабрика класса High Performance

3 голосов
/ 12 ноября 2010

Поскольку вы используете тег внедрения зависимости в своем вопросе, платформы внедрения зависимости обычно делают это для вас. Всегда присутствует отражение, но у большинства из них есть механизм кэширования, который предотвращает любое отражение при следующем запросе объекта. Особенно, когда ваш тип является конкретным типом с конструктором по умолчанию (как вы показали в своем вопросе), регистрация не требуется. Например, при использовании Simple Service Locator запрос будет выглядеть следующим образом:

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

Когда вы не хотите использовать инфраструктуру внедрения зависимостей, вы можете генерировать делегаты для создания этих объектов и кэшировать их в словаре с ключом objName (это в основном то, что будут делать платформы DI ). Хотя вы можете использовать LCG (как показал Шив), с новыми деревьями выражений .NET 3.5 это стало намного проще:

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();
}
1 голос
/ 12 ноября 2010

Вы можете использовать Microsoft.VisualBasic.Interaction.CreateObject, но это относится только к COM-объектам. (С другой стороны, это позволяет создавать объекты на компьютерах других людей.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...