Заменить динамический объект на T - PullRequest
0 голосов
/ 02 апреля 2019

У нас есть структура, которая содержит динамические данные, предоставленные одним источником, и ошибки в фиксированном формате, например:

struct AllOurInfo {
    public dynamic TheData {get;set;}
    public string[] Errors {get;set;}
}

Данные могут быть разными. Одна строка или коллекция различных типов.

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

Как бы вы превратили TheData в нединамический объект?

Я ищу что-то подобное (если это возможно)

AllOurInfo.TheData = EvaluateData(dData);
public ParentDataClass EvaluateData(dynamic dData)
{
    // Figure out the type of data, call the right class
    return new ChildDataClass()
}

struct AllOurInfo<T> {
    public T TheData {get;set;}  // or whatever class T is rather
    public string[] Errors {get;set;}
}

1 Ответ

1 голос
/ 02 апреля 2019

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

  1. Иметь базовый класс AllOurInfo только со свойством Errors, вы бы вернули это.
  2. Иметь класс AllOurInfo<T> : AllOurInfo.
  3. После определения типа T в EvaluateData используйте Reflection, чтобы создать экземпляр AllOurInfo<T> с определенным T и вернутьas AllOurInfo
  4. Приведите возвращаемое значение, где бы вы его не использовали, с AllOurInfo обратно на AllOurInfo<T>.

В целом, вы бы не выиграли слишком много, ивы не сможете сделать это, если не сможете использовать Reflection.

Я вижу здесь два варианта:

  1. Если у вас слишком много разных типов T, оставьте егокак есть.
  2. Если у вас их всего несколько, вы можете использовать фабричный подход:
public interface IAllOurInfo
{
    string[] Errors { get; }
}
public interface IAllOurInfo<T> : IAllOurInfo
{
    T TheData { get; }
}
public struct AllOurStringInfo : IAllOurInfo<string>
{
    public string[] Errors { get; private set; }
    public string TheData { get; private set; }

    public AllOurStringInfo(string[] errors, string theData)  : this()
    {
        Errors = errors;
        TheData = theData;
    }
}

public struct AllOurStringArrayInfo : IAllOurInfo<string[]>
{
    public string[] Errors { get; private set; }
    public string[] TheData { get; private set; }

    public AllOurStringArrayInfo(string[] errors, string[] theData) : this()
    {
        Errors = errors;
        TheData = theData;
    }
}

public IAllOurInfo EvaluateData(dynamic dData)
{
    // Figure out the type of data, call the right class

    // I am just giving an example here 
    if (dData.GetType() == typeof(string))
    {
        return new AllOurStringInfo(new[] { "Hello" }, "Hello");
    }

    // have no idea what I was given, return null or throw
    return null;
}

Конечно, вам все равно придется привести к ожидаемому типу.

...