Строка Доступ к символам
Есть два способа получить доступ к отдельному символу в строке. Первый - это метод
blockquote>charAt()
:return 'cat'.charAt(1); // returns "a"
Другой способ (введенный в ECMAScript 5) - это обрабатывать строку как массив объект, где отдельные символы соответствуют числовому индексу:
blockquote>return 'cat'[1]; // returns "a"
Вот мои 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" });
Сначала получите использование Текстового объекта Type.GetType(stringContainingTheGenericTypeArgument)
Затем используйте typeof(Repository<>).MakeGenericType(theTypeObject)
получить универсальный тип.
И наконец используйте Activator.CreateInstance
Это - задание для dynamic
ключевое слово, прибывающее в C# 4.0.
Существуют некоторые хорошие взломы здесь, которые получат Вас экземпляр Вашего объекта, но независимо от того, что текущая версия C# будет только знать, что это имеет object
, и это не может сделать многого с объектом отдельно, потому что текущий C# не поддерживает позднее связывание. Необходимо смочь, по крайней мере, бросить его к известному типу, чтобы сделать что-либо с ним. В конечном счете необходимо знать тип, в котором Вы нуждаетесь во время компиляции, или Вам не повезло.
Теперь, если можно ограничить класс репозитория к типам, реализовав некоторый известный интерфейс, Вы находитесь в намного лучшей форме.
Если я понимаю Ваш вопрос правильно... То, что Вы пытаетесь сделать, является взятием Ваш тип (Репозиторий <T>), и создайте определенную, универсальную реализацию из этого во времени выполнения?
Если так, смотрите на MakeGenericType. Можно использовать typeof (Репозиторий) и Система. Тип объекта Вы хотите для T и создаете его этот путь. После того как у Вас есть тип, Активатор. CreateInstance будет работать на Вас.
Предполагая, что Ваша строка содержит название типа, можно записать
object _rep = Activator.CreateInstance(typeof(Repository<>).MakeGenericType(Type.GetType(_sample)));
Однако _rep будет невведенным объектом, и у Вас не будет способа сделать что-либо с ним. Так как Вы не знаете то, что вводит универсальный класс, во время компиляции, нет никакого типа, к которому Вы бросаете его. (Если Репозиторий не наследовал неуниверсальный класс или реализует неуниверсальный интерфейс),
Вы могли решить это путем создания неуниверсального базового класса для Репозитория и кастинга объекта к нему.
Однако в зависимости от Вашей ситуации, Вы, вероятно, хотите сделать Repository
неуниверсальный класс.
Если Repository
класс, который содержит другие классы, вероятно, лучше сделать это неуниверсальным. Вы могли заставить его конструктора взять a Type
объект, и затем звонит Type.IsInstanceOfType
на каждом объекте Вы добавляете, чтобы удостовериться, что это - правильный тип.
Если Репозиторий является категоризированным набором вещей, вероятно, лучше сделать это неуниверсальным, и заставить его конструктора взять a string category
.
Если Вы хотите более определенный совет, отправьте больше деталей о Вас ситуация.
Type repType = typeof(Repository <>).MakeGenericType(Type.GetType("System.String"));
object rep = Assembly.GetAssembly(repType).CreateInstance(repType.FullName);
Это создало бы экземпляр Repository<string>
. Можно заменить "Систему. Строка" с любым типом Вам нравится.
Дженерики работают над типами, не над экземплярами. Можно читать больше здесь.
Кажется, что просто необходимо добавить конструктора к классу, который берет в желаемом типе и инициализирует значение:
public class Foo<T>
{
private T = default(T);
public Foo(T initValue)
{
_val = T;
}
}
Это - "вид" возможного. Вид, в котором можно сделать это, но это - определенный взлом.
У Вас есть 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
, который сохранит Вас кастинг.
"T" в Универсальном классе обозначает тип, не экземпляр типа. Таким образом, если Вы хотите, чтобы Ваш репозиторий содержал строковые объекты, затем используйте
var _rep = new Repository<string>();