«Где это: класс» неправильный синтаксис - PullRequest
0 голосов
/ 04 декабря 2018
public static class Extensions
{
    public static T TryCast<T>(this object parent)
        where T : class
        where this : class
    {
        T child = (T)Activator.CreateInstance(typeof(T));
        foreach (PropertyInfo prop in parent.GetType().GetProperties())
        {
            child.GetType().GetProperty(prop.Name)?.SetValue(child, prop.GetValue(parent));
        }

        return child;
    }
}

TryCast может использоваться как:

someString.TryCast ()

, но не ограничивается только классами, так как "гдеthis: class «возвращает синтаксическую ошибку», что означает, что без ограничения «this: class» он будет появляться с такими переменными, как int, char и т. д.

Я ищу способ ограничения типа«этот родительский объект» только для переменных класса, поскольку в моем случае использования не имеет смысла использовать его на простых типах, таких как int и char.

Примечание:

Можно захватить и ограничить тип родительского элемента следующим образом:

public static T2 TryCastWorse<T, T2>(this T parent)
    where T : class
    where T2 : class
{
    T2 child = (T2)Activator.CreateInstance(typeof(T2));
    foreach (PropertyInfo prop in parent.GetType().GetProperties())
    {
        child.GetType().GetProperty(prop.Name)?.SetValue(child, prop.GetValue(parent));
    }

    return child;
}

И затем использовать его следующим образом:

someString.TryCastWorse ()

Это не оптимально, так как нужно указать класс вызывающей переменной, как указано в первом типе в <>, который является строкой, которая всегда должна быть равна someString.

Это не предназначенная функциональность в данном случае, так какможет привести к ошибкам в некоторых случаях использования.

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Похоже, вы хотите, чтобы более чистый синтаксис вызывал конструктор отражения для стандартных классов.К сожалению, если вам нужны проверки обобщенных типов, вам необходимо передать их вместе с синтаксисом <T> методу.

Возможно, альтернативой является то, что все ваши стандартные шаблоны расширяют абстрактный класс, имеющий ConvertTo<T>() метод:

public abstract class ABoilerplate {
    public T ConvertTo<T>() where T : class {
        T child = (T)Activator.CreateInstance(typeof(T));
        foreach (System.Reflection.FieldInfo fi in typeof(T).GetFields().Where(field => !field.IsStatic))//should do validations
            fi.SetValue(
                child,
                this.GetType().GetField(fi.Name).GetValue(this));
        return child;
    }
}
public class SimpleClass : ABoilerplate {
    public int ID;
}
public class DuplicateSimpleClass {
    public int ID;
}

Затем используйте как

SimpleClass instance1 = new SimpleClass() { ID = 1 };
DuplicateSimpleClass instance2 = instance1.ConvertTo<DuplicateSimpleClass>();
0 голосов
/ 04 декабря 2018

Ответ просто нет.Вы не можете ограничить аргумент, чтобы он не был типом значения, если только он не является аргументом универсального типа с ограничением class.

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

...