Как я создаю универсальный класс из строки в C#? [дубликат]

Строка Доступ к символам

Есть два способа получить доступ к отдельному символу в строке. Первый - это метод charAt():

blockquote>
return 'cat'.charAt(1); // returns "a"

Другой способ (введенный в ECMAScript 5) - это обрабатывать строку как массив объект, где отдельные символы соответствуют числовому индексу:

blockquote>
return 'cat'[1]; // returns "a"

16
задан SLaks 30 August 2009 в 20:56
поделиться

9 ответов

Вот мои 2 цента:

Type genericType = typeof(Repository<>);
Type[] typeArgs = { Type.GetType("TypeRepository") };
Type repositoryType = genericType.MakeGenericType(typeArgs);

object repository = Activator.CreateInstance(repositoryType);

Ответ на вопрос в комментарии.

MethodInfo genericMethod = repositoryType.GetMethod("GetMeSomething");
MethidInfo closedMethod = genericMethod.MakeGenericMethod(typeof(Something));
closedMethod.Invoke(repository, new[] { "Query String" });
24
ответ дан 30 November 2019 в 16:01
поделиться

Сначала получите использование Текстового объекта Type.GetType(stringContainingTheGenericTypeArgument)

Затем используйте typeof(Repository<>).MakeGenericType(theTypeObject) получить универсальный тип.

И наконец используйте Activator.CreateInstance

16
ответ дан 30 November 2019 в 16:01
поделиться

Это - задание для dynamic ключевое слово, прибывающее в C# 4.0.

Существуют некоторые хорошие взломы здесь, которые получат Вас экземпляр Вашего объекта, но независимо от того, что текущая версия C# будет только знать, что это имеет object, и это не может сделать многого с объектом отдельно, потому что текущий C# не поддерживает позднее связывание. Необходимо смочь, по крайней мере, бросить его к известному типу, чтобы сделать что-либо с ним. В конечном счете необходимо знать тип, в котором Вы нуждаетесь во время компиляции, или Вам не повезло.

Теперь, если можно ограничить класс репозитория к типам, реализовав некоторый известный интерфейс, Вы находитесь в намного лучшей форме.

3
ответ дан 30 November 2019 в 16:01
поделиться

Если я понимаю Ваш вопрос правильно... То, что Вы пытаетесь сделать, является взятием Ваш тип (Репозиторий <T>), и создайте определенную, универсальную реализацию из этого во времени выполнения?

Если так, смотрите на MakeGenericType. Можно использовать typeof (Репозиторий) и Система. Тип объекта Вы хотите для T и создаете его этот путь. После того как у Вас есть тип, Активатор. CreateInstance будет работать на Вас.

2
ответ дан 30 November 2019 в 16:01
поделиться

Предполагая, что Ваша строка содержит название типа, можно записать

object _rep = Activator.CreateInstance(typeof(Repository<>).MakeGenericType(Type.GetType(_sample)));

Однако _rep будет невведенным объектом, и у Вас не будет способа сделать что-либо с ним. Так как Вы не знаете то, что вводит универсальный класс, во время компиляции, нет никакого типа, к которому Вы бросаете его. (Если Репозиторий не наследовал неуниверсальный класс или реализует неуниверсальный интерфейс),

Вы могли решить это путем создания неуниверсального базового класса для Репозитория и кастинга объекта к нему.

Однако в зависимости от Вашей ситуации, Вы, вероятно, хотите сделать Repository неуниверсальный класс.

Если Repository класс, который содержит другие классы, вероятно, лучше сделать это неуниверсальным. Вы могли заставить его конструктора взять a Type объект, и затем звонит Type.IsInstanceOfType на каждом объекте Вы добавляете, чтобы удостовериться, что это - правильный тип.

Если Репозиторий является категоризированным набором вещей, вероятно, лучше сделать это неуниверсальным, и заставить его конструктора взять a string category.

Если Вы хотите более определенный совет, отправьте больше деталей о Вас ситуация.

2
ответ дан 30 November 2019 в 16:01
поделиться
Type repType = typeof(Repository <>).MakeGenericType(Type.GetType("System.String"));
object rep = Assembly.GetAssembly(repType).CreateInstance(repType.FullName);

Это создало бы экземпляр Repository<string>. Можно заменить "Систему. Строка" с любым типом Вам нравится.

1
ответ дан 30 November 2019 в 16:01
поделиться

Дженерики работают над типами, не над экземплярами. Можно читать больше здесь.

Кажется, что просто необходимо добавить конструктора к классу, который берет в желаемом типе и инициализирует значение:

public class Foo<T>
{
    private T = default(T);

    public Foo(T initValue)
    {
        _val = T;
    }
}
0
ответ дан 30 November 2019 в 16:01
поделиться

Это - "вид" возможного. Вид, в котором можно сделать это, но это - определенный взлом.

У Вас есть 3 опции:

Если Вы знаете свои классы впереди, используйте оператор переключения. В основном как это:

switch(str){
   case "TypeRepository": return new Repository<TypeRepository>;
}

Как более усовершенствованная форма вышеупомянутого, можно использовать словарь вместо хеш-таблицы

var factory = new Dictionary<string, Func<object>>();
factory.Add( "TypeRepository", () => new Repository<TypeRepository>() );

var theObject = factory["TypeRepository"]() as Repository<TypeRepository>;

Для самой большой гибкости можно использовать отражение для строк совпадения к классам во времени выполнения. Знайте, что отражение является довольно медленным, поэтому при выполнении этого с каким-либо видом регулярности Вы хотите избежать его. Как пример, Вот один метод Frans Bouma использования. Просто изменение List<> кому: Repository<> в Вашем коде:

public static object MakeList( string typeStr )
{
    var nameSpace = "MyTestApplication" + ".";

    var objType = Type.GetType(nameSpace + typeStr); // NAMESPACE IS REQUIRED
    var listType = typeof(List<>).MakeGenericType(objType);
    return Activator.CreateInstance(listType);
}

var listOfThings = MakeList("MyCoolObject") as List<MyCoolObject>;

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

Это неизбежно, потому что Вы не знаете тип списка до времени выполнения, и C# создается вокруг знания вещей во время компиляции (это - то, что имеют в виду люди, когда они говорят "язык программирования со статическим контролем типов"). Это будет менее болезненно в C#4, где Вы сможете возвратиться dynamic, который сохранит Вас кастинг.

0
ответ дан 30 November 2019 в 16:01
поделиться

"T" в Универсальном классе обозначает тип, не экземпляр типа. Таким образом, если Вы хотите, чтобы Ваш репозиторий содержал строковые объекты, затем используйте

var _rep = new Repository<string>();
-3
ответ дан 30 November 2019 в 16:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: