Метод с параметром типа для возврата массива указанного типа - PullRequest
0 голосов
/ 15 июля 2011

Я пытаюсь создать универсальный метод в C #, который будет возвращать массив указанного типа.Вот как выглядит мой метод на данный момент:

private T[] GetKeys<T>(string key, Dictionary<string, object> obj) where T : new()
{
    if (obj.ContainsKey(key))
    {
        object[] objs = (object[])obj[key];
        T[] list = new T[objs.Length];
        for (int i = 0; i < objs.Length; i++)
        {
            list[i] = (T)Activator.CreateInstance(
                             typeof(T),
                             new object[] {
                                 (Dictionary<string, object>)objs[i] 
                             });
        }
        return list;
    }
    else
    {
        return null;
    }
}

Поскольку этот класс используется внутри и недоступен при использовании библиотеки, я уже знаю, какие классы будут помещены в <T>.Все классы имеют одинаковые параметры в своих конструкторах.Но я должен был предоставить им открытый конструктор без параметров, прежде чем этот код даже скомпилируется.Теперь, когда я добираюсь до линии Activator.CreateInstance, я получаю сообщение об ошибке Constructor on type 'MyNamespace.MyClass+MyOtherClass' not found.MyClass это класс, который содержит метод выше.MyOtherClass - это класс, который передается как T.

Любая помощь будет оценена Спасибо!

Ответы [ 3 ]

2 голосов
/ 15 июля 2011

Это должно работать для вас, пока ваш конструктор выглядит так:

public MyType (Dictionary<string,object> dict)
{
}

Если ваши конструкторы не являются публичными, вам нужно изменить GetConstructor, чтобы передать BindingFlags.NonPublic.

        private T[] GetKeys<T>(string key, Dictionary<string, object> obj)
        // Since you're not using the default constructor don't need this:
        //   where T : new()
        {
            if (obj.ContainsKey(key))
            {
                object[] objs = (object[])obj[key];
                T[] list = new T[objs.Length];
                for (int i = 0; i < objs.Length; i++)
                {
                    list[i] = (T)typeof(T).GetConstructor(new [] {typeof(Dictionary<string,object>)}).Invoke (new object[] {
                                         (Dictionary<string, object>)objs[i] 
                                     });
                }
                return list;
            }
            else
            {
                return null;
            }
        }
1 голос
/ 15 июля 2011

Ваши GetKeys требуют, чтобы T имел открытый конструктор без параметров :

private T[] GetKeys<T>(...) where T : new()
                                       ↑

Это ограничение на T позволяет вам писать код, подобный этому, в теле метода:

T t = new T();

Так как вы не используете это, но ожидаете некоторого другого конструктора (который не может быть применен как открытый конструктор без параметров), просто удалите ограничение, и оно должно работать.

0 голосов
/ 15 июля 2011

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

...