C# 转换为使用泛型
我已经试过好几次了,我总是让自己陷入困境。如何将此代码更改为基于泛型的方法?此代码遵循“四人帮”组合模式C# 转换为使用泛型,c#,generics,C#,Generics,我已经试过好几次了,我总是让自己陷入困境。如何将此代码更改为基于泛型的方法?此代码遵循“四人帮”组合模式 public abstract class AdjacencyTreeBase { public AdjacencyTreeBase(int entityId, int entityTypeId) { EntityId = entityId; EntityTypeId = entityTypeId; } public long
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 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;
}
public List CreateSample()
{
//构建树的底部对象。。。
var client1=新的邻接客户机(1,4)
{
first_name=“Pic'nic”,
last_name=“Basket#1”,
ssn=“123-45-6789”
};
var client2=新的邻接客户端(2,4)
{
first_name=“Pic'nic”,
last_name=“Basket#2”,
ssn=“234-56-7890”
};
var client3=新的邻接客户端(3,4)
{
first_name=“熊”,
last_name=“Cave”,
ssn=“345-67-8901”
};
var client4=新的邻接客户端(4,4)
{
first_name=“野餐”,
last_name=“Table”,
ssn=“456-78-9012”
};
//构建下一个级别并添加子级。。。
var officer1=新的邻接用户(1,3)
{
first_name=“Yogi”,
last_name=“熊”,
官员编号=“YB123”
};
官员1.AddChild(客户1);
官员1.AddChild(客户2);
var officer2=新的邻接用户(2,3)
{
first_name=“公园”,
last_name=“Ranger”,
官员编号=“PR123”
};
官员2.AddChild(客户3);
职员2.AddChild(客户4);
//构建树的顶部并添加中间的子级。。。
var AgencyThathareadyExists=新邻接(1,2)
{
机构名称=“水母”,
机构类型=“公园”,
};
已存在的代理。AddChild(办公室1);
已存在的代理。添加儿童(2号官员);
已经存在的退货代理;
}
虽然我的示例非常简单,但我们的实体结构并不是那么简单。我们目前有7个不同的实体,几乎任何类型的实体都可以是任何类型实体的子实体,其兄弟实体也可以是各种类型
短暂性脑缺血发作
编辑:
试图澄清:子对象(以及子对象的子对象)可以是任何实体类型(代理、用户、官员、客户等)。虽然所有实体都有共同的属性基础,但每个对象的其余部分彼此不同。当从数据库中提取时,我可能会请求一个代理,并希望该代理下的整个层次结构。直接子代可以包括所有类型,每个子代可以有包含所有类型的子代。非常混乱,非常灵活。我想我不太确定你希望完成什么,但我可以告诉你很多 首先,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"
}
};
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);
}
}
public AdjacencyUser(int entityId) : base(entityId, 3)
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 };
}
但这实际上取决于它是否有用。有些人可能会反对添加此项,因为它不必要地重复了构造函数参数。当然,这取决于你。这只是另一个例子
除此之外,我很想从所有东西中删除entityTypeId
,除非您绝对需要它。这取决于您希望如何使用它,但我根据您的实现将其留在这里。看起来您可以根据T
推断出它,但我也不确定为什么在实现中需要它
根据我的理解,即使没有包含泛型,您现有的传递构造函数也可能如下所示:
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"
}
};
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);
}
}
public AdjacencyUser(int entityId) : base(entityId, 3)
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 };
}
从而消除了一些冗余。当然,这取决于两个“用户”类型始终具有相同的EntityTypeId
,这可能公平,也可能不公平
我不确定我是否真的回答了你的问题,但希望它能指引你一个正确的方向 这可以使类层次结构强类型化,并符合
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)
{
}
}
对于每个EntityTypeId,EntityID都是唯一的。如果没有EntityTypeId,这是不可能的。这是10年以上增长挑战的一部分。从用户开始,然后增加了代理和客户。这就是其他人“聪明地”认为每个实体的ID(UserId、ClientId等)可以映射到一个复合键以简化映射关系的点。从那时起,设备、客户和更多的产品被添加。让我明天玩,看看你的例子是否更容易阅读/使用。如果是这样的话,这就是答案。@KeithBarrows,这很公平。传统的东西从来都不好玩。我的观点是,您不需要在构造函数中接受typeId。我在最后一个代码块中添加了一个示例。当然,这是非常相切的,而且它是基于可能不真实的假设。只是一个建议。但是,对于泛型,它们确实会改变代码的流程。添加一个额外的属性级别既有好处(比如,如果您愿意,您的实体可以有一个
子属性,而现在这会导致冲突),也有缺点(额外键入?我真的不介意)。老实说,我会这么做,只是为了可读性,但我能想象的最大的用例是使用ORM。如果EF(或其他什么)正在为您序列化User
对象,您就不必将它们映射到这个节点类型,这很方便。除此之外,它只是语义。我选择了构造函数中的两个参数,因为这总是必需的。没有任何情况下,任何对象都会在没有至少这两个数据的情况下被实例化。您这里的实际问题还不清楚。你想要什么?根据您的最后一段,听起来您只是想限制最后的类,只允许添加一种类型(它们自己)。但是CreateSample
方法似乎建议您创建一个复合类型。你能更清楚地回答你要问的问题吗