2016-03-10 2 views
3

Я пробовал несколько раз, и я продолжаю входить в цикл. Как бы вы изменили этот код на общий подход? Этот код следует за Группой четырех композитных узоров.Преобразование в использование Generics

public abstract class AdjacencyTreeBase 
{ 
    public AdjacencyTreeBase(int entityId, int entityTypeId) 
    { 
     EntityId = entityId; 
     EntityTypeId = entityTypeId; 
    } 

    public long? Id { get; set; } 
    public int? SystemId { get; set; } 
    public int EntityId { get; set; } 
    public int EntityTypeId { get; set; } 
    public bool? isActive { get; set; } 
    public long? lft { get; set; } 
    public long? rgt { get; set; } 

    public abstract void AddChild(AdjacencyTreeBase c); 
    public abstract void RemoveChild(AdjacencyTreeBase c); 
    public abstract List<AdjacencyTreeBase> ListChildren(); 
    public abstract void AddChildren(List<AdjacencyTreeBase> c); 
    public abstract void ReplaceChildren(List<AdjacencyTreeBase> c); 
} 

public class AdjacencyTree : AdjacencyTreeBase 
{ 
    private List<AdjacencyTreeBase> _children = new List<AdjacencyTreeBase>(); 
    public List<AdjacencyTreeBase> Children { get { return _children; } set { _children = value; } } 

    public AdjacencyTree(int entityId, int entityTypeId) : base(entityId, entityTypeId) { } 

    public override void AddChild(AdjacencyTreeBase component) 
    { 
     _children.Add(component); 
    } 
    public override void AddChildren(List<AdjacencyTreeBase> c) 
    { 
     _children = c; 
    } 
    public override void ReplaceChildren(List<AdjacencyTreeBase> c) 
    { 
     _children = c; 
    } 
    public override void RemoveChild(AdjacencyTreeBase component) 
    { 
     _children.Remove(component); 
    } 
    public override List<AdjacencyTreeBase> ListChildren() 
    { 
     return _children; 
    } 
} 

public class AdjacencyAgency : AdjacencyTree 
{ 
    public string agency_name { get; set; } 
    public string customer_number { get; set; } 
    public string agency_type { get; set; } 

    public AdjacencyAgency(int entityId, int entityTypeId) : base(entityId, entityTypeId) 
    { 
    } 
} 

public class AdjacencyUser : AdjacencyTree 
{ 
    public string officer_number { get; set; } 
    public string last_name { get; set; } 
    public string first_name { get; set; } 
    public string middle_initial { get; set; } 

    public AdjacencyUser(int entityId, int entityTypeId) : base(entityId, entityTypeId) 
    { 
    } 
} 

public class AdjacencyClient : AdjacencyTree 
{ 
    public string last_name { get; set; } 
    public string first_name { get; set; } 
    public string middle_initial { get; set; } 
    public string ssn { get; set; } 

    public AdjacencyClient(int entityId, int entityTypeId) : base(entityId, entityTypeId) 
    { 
    } 
} 

Образец инстанцировании этого объекта карты:

public List<AdjacencyTreeBase> CreateSample() 
{ 
    // build bottom of tree objects... 
    var client1 = new AdjacencyClient(1, 4) 
    { 
     first_name = "Pic'nic", 
     last_name = "Basket #1", 
     ssn = "123-45-6789" 
    }; 
    var client2 = new AdjacencyClient(2, 4) 
    { 
     first_name = "Pic'nic", 
     last_name = "Basket #2", 
     ssn = "234-56-7890" 
    }; 
    var client3 = new AdjacencyClient(3, 4) 
    { 
     first_name = "Bear", 
     last_name = "Cave", 
     ssn = "345-67-8901" 
    }; 
    var client4 = new AdjacencyClient(4, 4) 
    { 
     first_name = "Picnic", 
     last_name = "Table", 
     ssn = "456-78-9012" 
    }; 

    // build the next level up and add the children... 
    var officer1 = new AdjacencyUser(1, 3) 
    { 
     first_name = "Yogi", 
     last_name = "Bear", 
     officer_number = "YB123" 
    }; 
    officer1.AddChild(client1); 
    officer1.AddChild(client2); 

    var officer2 = new AdjacencyUser(2, 3) 
    { 
     first_name = "Park", 
     last_name = "Ranger", 
     officer_number = "PR123" 
    }; 
    officer2.AddChild(client3); 
    officer2.AddChild(client4); 

    // build the top of the tree and add the middle children... 
    var agencyThatAlreadyExists = new AdjacencyAgency(1, 2) 
    { 
     agency_name = "Jellystone", 
     agency_type = "Park", 
    }; 
    agencyThatAlreadyExists.AddChild(officer1); 
    agencyThatAlreadyExists.AddChild(officer2); 

    return agencyThatAlreadyExists; 
} 

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

ТИА

EDIT: Чтобы попытаться уточнить: дети (и дети детей) могут быть любым типа объекта (агентства, пользователь, должностное лицо, клиент и т.д.). Хотя все объекты имеют общую базу свойств, остальная часть каждого объекта отличается друг от друга. Когда вы выходите из базы данных, я могу подать запрос в агентство и хочу, чтобы вся иерархия находилась под этим одним агентством. Прямые потомки могут включать все типы, у каждого ребенка могут быть потомки, которые включают все типы. Очень грязный, очень гибкий.

+0

Ваш фактический вопрос здесь остается неясным. Что ты хочешь? На основе вашего заключительного абзаца вам кажется, что вы просто хотите ограничить конечные классы только тем, чтобы добавить один тип (себя). Но метод 'CreateSample', кажется, предполагает, что вы хотите создать составной тип. Можете ли вы уточнить вопрос, который вы задаете? – Enigmativity

ответ

1

Это работает, чтобы сделать вашу иерархию классов сильно типизированных & соответствуют CreateSample код:

public abstract class AdjacencyTreeBase<T> where T : AdjacencyTreeBase<T> 
{ 
    public AdjacencyTreeBase(int entityId, int entityTypeId) 
    { 
     EntityId = entityId; 
     EntityTypeId = entityTypeId; 
    } 

    public long? Id { get; set; } 
    public int? SystemId { get; set; } 
    public int EntityId { get; set; } 
    public int EntityTypeId { get; set; } 
    public bool? isActive { get; set; } 
    public long? lft { get; set; } 
    public long? rgt { get; set; } 

    public abstract void AddChild(T c); 
    public abstract void RemoveChild(T c); 
    public abstract List<T> ListChildren(); 
    public abstract void AddChildren(List<T> c); 
    public abstract void ReplaceChildren(List<T> c); 
} 

public abstract class AdjacencyTree : AdjacencyTreeBase<AdjacencyTree> 
{ 
    private List<AdjacencyTree> _children = new List<AdjacencyTree>(); 
    public List<AdjacencyTree> Children { get { return _children; } set { _children = value; } } 

    public AdjacencyTree(int entityId, int entityTypeId) : base(entityId, entityTypeId) { } 

    public override void AddChild(AdjacencyTree component) 
    { 
     _children.Add(component); 
    } 
    public override void AddChildren(List<AdjacencyTree> c) 
    { 
     _children = c; 
    } 
    public override void ReplaceChildren(List<AdjacencyTree> c) 
    { 
     _children = c; 
    } 
    public override void RemoveChild(AdjacencyTree component) 
    { 
     _children.Remove(component); 
    } 
    public override List<AdjacencyTree> ListChildren() 
    { 
     return _children; 
    } 
} 

public class AdjacencyAgency : AdjacencyTree 
{ 
    public string agency_name { get; set; } 
    public string customer_number { get; set; } 
    public string agency_type { get; set; } 

    public AdjacencyAgency(int entityId, int entityTypeId) : base(entityId, entityTypeId) 
    { 
    } 
} 

public class AdjacencyUser : AdjacencyTree 
{ 
    public string officer_number { get; set; } 
    public string last_name { get; set; } 
    public string first_name { get; set; } 
    public string middle_initial { get; set; } 

    public AdjacencyUser(int entityId, int entityTypeId) : base(entityId, entityTypeId) 
    { 
    } 
} 

public class AdjacencyClient : AdjacencyTree 
{ 
    public string last_name { get; set; } 
    public string first_name { get; set; } 
    public string middle_initial { get; set; } 
    public string ssn { get; set; } 

    public AdjacencyClient(int entityId, int entityTypeId) : base(entityId, entityTypeId) 
    { 
    } 
} 

Затем CreateSample нужно изменить, как это:

public List<AdjacencyTree> CreateSample() 
{ 
    // build bottom of tree objects... 
    var client1 = new AdjacencyClient(1, 4) 
    { 
     first_name = "Pic'nic", 
     last_name = "Basket #1", 
     ssn = "123-45-6789" 
    }; 
    var client2 = new AdjacencyClient(2, 4) 
    { 
     first_name = "Pic'nic", 
     last_name = "Basket #2", 
     ssn = "234-56-7890" 
    }; 
    var client3 = new AdjacencyClient(3, 4) 
    { 
     first_name = "Bear", 
     last_name = "Cave", 
     ssn = "345-67-8901" 
    }; 
    var client4 = new AdjacencyClient(4, 4) 
    { 
     first_name = "Picnic", 
     last_name = "Table", 
     ssn = "456-78-9012" 
    }; 

    // build the next level up and add the children... 
    var officer1 = new AdjacencyUser(1, 3) 
    { 
     first_name = "Yogi", 
     last_name = "Bear", 
     officer_number = "YB123" 
    }; 
    officer1.AddChild(client1); 
    officer1.AddChild(client2); 

    var officer2 = new AdjacencyUser(2, 3) 
    { 
     first_name = "Park", 
     last_name = "Ranger", 
     officer_number = "PR123" 
    }; 
    officer2.AddChild(client3); 
    officer2.AddChild(client4); 

    // build the top of the tree and add the middle children... 
    var agencyThatAlreadyExists = new AdjacencyAgency(1, 2) 
    { 
     agency_name = "Jellystone", 
     agency_type = "Park", 
    }; 
    agencyThatAlreadyExists.AddChild(officer1); 
    agencyThatAlreadyExists.AddChild(officer2); 

    return new List<AdjacencyTree>() { agencyThatAlreadyExists }; 
} 
+0

Добавлен EDIT в нижней части вопроса. My CreateSample - это всего лишь небольшой предварительный просмотр «что может быть». У вас в основном есть: в верхней части находится единая сущность (любой тип). У этого объекта могут быть дети (любого типа). Эти дети могут иметь детей (любого типа). –

+0

@KeithBarrows - Я обновил код, который, я думаю, работает для вашего кода. – Enigmativity

0

Я думаю, я не совсем уверен, чего вы надеетесь достичь, но я могу сказать вам это много.

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

Это говорит, что я буду делать, что-то вроде этого:

public class AdjacencyTree<T> : AdjacencyTree 
{ 
    public AdjacencyTree(int entityId, int entityTypeId) : base(entityId, entityTypeId) { } 

    public T Value { get; set; } 
} 

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

Вы, конечно же, то нужно создать экземпляр их так:

var client1 = new AdjacencyTree<Client>(1, 4) 
{ 
    Value = new Client() 
    { 
     first_name = "Pic'nic", 
     last_name = "Basket #1", 
     ssn = "123-45-6789" 
    } 
}; 

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

Если вы хотите быть очень умным, вы можете добавить метод, как это:

public class AdjacencyTree<T> : AdjacencyTree 
{ 
    // ... 

    public void AddChild<TChild>(int entityId, int entityTypeId, TChild child) 
    { 
     var child = new AdjacencyTree<TChild>(entityId, entityTypeId) 
     { 
      Value = child 
     }; 
     this.AddChild(child); 
    } 
} 

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

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

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

public AdjacencyUser(int entityId) : base(entityId, 3) 

Таким образом удаляя некоторую избыточность. Конечно, это зависит от того, что два типа «Пользователь» всегда будут иметь одинаковые EntityTypeId, что может быть или не быть справедливым.

Я не уверен, действительно ли я ответил на ваш вопрос здесь, но, надеюсь, это приведет вас в правильном направлении!

+0

Для каждого EntityTypeId EntityIds уникальны. Это невозможно сказать без EntityTypeIds. Часть 10-летнего возраста. Начались только с Пользователей, затем добавлены агентства и клиенты. Речь идет о том, что кто-то еще «умно» считает, что каждый идентификатор Entity (UserId, ClientId и т. Д.) Может быть сопоставлен с составным ключом, чтобы упростить сопоставления отношений. С тех пор были добавлены устройства, клиенты и т. Д. Позвольте мне сыграть завтра, чтобы узнать, облегчает ли ваш пример чтение/использование. Если это так, это будет ответ. –

+0

@KeithBarrows достаточно. Наследие никогда не бывает забавным. Моя точка зрения была больше того, что вам не нужно принимать typeId в конструкторе. Я добавил пример в мой последний блок кода. Конечно, это довольно касательно, и оно основано на предположениях, которые могут быть неверными. Просто предложение. –

+0

Но, как и для дженериков, они меняют поток вашего кода. Добавление дополнительного уровня свойства имеет свои преимущества (например, ваш объект может иметь свойство «Дети», если вы хотите, тогда как это может вызвать конфликт сейчас) и недостатки (дополнительная набрав? На самом деле, я не против). Я бы пошла на это, честно говоря, только для удобства чтения, но самый большой случай использования, который я могу себе представить, придет в использовании ORM. Если EF (или что-то другое) сериализует для вас объекты 'User', вам не нужно будет сопоставлять их с этим типом узла, что удобно. Помимо этого, это просто семантика. –

Смежные вопросы