比方说,我有一个接口,它基本上是两个子接口的组合。其背后的想法是,我有两个不同的API。提供有关一个人的公共信息的一种。并且一次提供“秘密”信息。看起来可能像这样:
public interface IPublicPersonData
{
// The ID is the key
int PersonId { get; set; }
// This property is specific to this part
string Name {get; set; }
}
public interface ISecretPersonData
{
// The ID is the key
int PersonId { get; set; }
// This property is specific to this part
decimal AnnualSalary{ get; set; }
}
public interface IPerson: IPublicPersonData, ISecretPersonData
{
// No new stuff, this is merely a combination of the two.
}
所以基本上我得到两个列表。一个List<IPublicPersonData>
和一个List<ISecretPersonData>
。我想将它们加入成为一个List<IPerson>
,最好使用LINQ。
即使存在逻辑(在实现接口的接口方法中),我也无法找到关于如何根据输入类型控制LINQ输出类型的任何信息。
public List<IPerson> JoinPersonData(
List<IPublicPersonData> publicData,
List<ISecretPersonData> secretData)
{
// What the heck goes here?
}
答案 0 :(得分:4)
假设您编写了一种方法,例如:
public ISomething CombinePersonWithSecret(
IPublicPersonData publicPerson,
ISecretPersonData secret)
{
if(publicPerson.PersonId != secret.PersonId)
{
throw ...;
}
//join 2 params into a single entity
return something;
}
现在您可以...
IEnumerable<ISomething> secretivePeople = PublicPeople.Join(
SecretPersonData,
publicPerson => publicPerson.PersonId,
secret => secret.PersonId,
(publicPerson, secret) => CombinePersonWithSecret(publicPerson, secret))
答案 1 :(得分:3)
问题不在Join中,而是在您要返回的IPerson中。 Join方法的参数之一是如何处理联接结果。
您想将它们加入实现IPerson
的新对象中。如果您已经有了这样一个对象:太好了,请使用该对象;如果您没有,那么这里是一个简单的对象:
public PersonData : IPerson // and thus also IPublicPersonData and ISecretPersonData
{
// this PersonData contains both public and secret data:
public IPublicPersonData PublicPersonData {get; set;}
public ISecretPersnData SecretPersonData {get; set;}
// implementation of IPerson / IPublicPersonData / ISecretPersonData
int PersonId
{
get {return this.PublicPersonData.Id; }
set
{ // update both Ids
this.PublicPersonData.Id = value;
this.SecreatPersonData.Id = value;
}
}
public string Name
{
get { return this.PublicPersonData.Name; },
set {this.PublicPersonData.Name = value;}
}
public decimal AnnualSalary
{
get {return this.SecretPersonData.AnnualSalary;},
set {this.SecretPersnData.AnnualSalary = value;
}
}
此对象不需要复制特殊数据和秘密人员数据的值。但是请记住,如果更改值,则原始数据也会更改。如果您不想这样做,则在创建对象时需要复制数据
IEnumerable<IPublicPersonData> publicData = ...
IEnumerable<ISecretPersonData> secretData = ...
// Join these two sequences on same Id. Return as an IPerson
IEnumerable<IPerson> joinedPerson = publicData // take the public data
.Join(secretData, // inner join with secret data
publicPerson => publicPerson.Id, // from every public data take the Id
secretPerson => secretPerson.Id, // from every secret data take the Id
(publicPerson, secretPerson) => new PersonData() // when they match make a new PersonData
{
PublicPersonData = publicPerson,
SecretPersnData = secretPerson,
});
答案 2 :(得分:0)
LINQ的Join method为您完成这项工作。假设有一个Person : IPerson
类,这是实现JoinPersonData
方法的两种方法:
public static IEnumerable<IPerson> LiteralJoinPersonData(List<IPublicPersonData> publics, List<ISecretPersonData> secrets)
{
return from p in publics
join s in secrets on p.PersonId equals s.PersonId
select new Person(p.PersonId, p.Name, s.AnnualSalary);
}
public static IEnumerable<IPerson> FunctionalJoinPersonData(List<IPublicPersonData> publics, List<ISecretPersonData> secrets)
{
return publics
.Join<IPublicPersonData, ISecretPersonData, int, IPerson>(
secrets,
p => p.PersonId,
s => s.PersonId,
(p, s) => new Person(p.PersonId, p.Name, s.AnnualSalary));
}