모든 인터페이스 정의
가있는 프로젝트가 있습니다 : RivWorks.Interfaces 구체적인 구현을 정의하는 프로젝트가 있습니다 : RivWorks.DTO
이 작업을 전에 수백 번 수행했지만 어떤 이유로 지금이 오류가 발생합니다.
암시 적으로 ‘System.Collections.Generic.List <RivWorks.DTO.Product>’형식을 ‘System.Collections.Generic.List <RivWorks.Interfaces.DataContracts.IProduct>’로 변환 할 수 없습니다.
인터페이스 정의 (단축) :
namespace RivWorks.Interfaces.DataContracts
{
public interface IProduct
{
[XmlElement]
[DataMember(Name = "ID", Order = 0)]
Guid ProductID { get; set; }
[XmlElement]
[DataMember(Name = "altID", Order = 1)]
long alternateProductID { get; set; }
[XmlElement]
[DataMember(Name = "CompanyId", Order = 2)]
Guid CompanyId { get; set; }
...
}
}
구체적인 클래스 정의 (단축) :
namespace RivWorks.DTO
{
[DataContract(Name = "Product", Namespace = "http://rivworks.com/DataContracts/2009/01/15")]
public class Product : IProduct
{
#region Constructors
public Product() { }
public Product(Guid ProductID)
{
Initialize(ProductID);
}
public Product(string SKU, Guid CompanyID)
{
using (RivEntities _dbRiv = new RivWorksStore(stores.RivConnString).NegotiationEntities())
{
model.Product rivProduct = _dbRiv.Product.Where(a => a.SKU == SKU && a.Company.CompanyId == CompanyID).FirstOrDefault();
if (rivProduct != null)
Initialize(rivProduct.ProductId);
}
}
#endregion
#region Private Methods
private void Initialize(Guid ProductID)
{
using (RivEntities _dbRiv = new RivWorksStore(stores.RivConnString).NegotiationEntities())
{
var localProduct = _dbRiv.Product.Include("Company").Where(a => a.ProductId == ProductID).FirstOrDefault();
if (localProduct != null)
{
var companyDetails = _dbRiv.vwCompanyDetails.Where(a => a.CompanyId == localProduct.Company.CompanyId).FirstOrDefault();
if (companyDetails != null)
{
if (localProduct.alternateProductID != null && localProduct.alternateProductID > 0)
{
using (FeedsEntities _dbFeed = new FeedStoreReadOnly(stores.FeedConnString).ReadOnlyEntities())
{
var feedProduct = _dbFeed.AutoWithImage.Where(a => a.ClientID == companyDetails.ClientID && a.AutoID == localProduct.alternateProductID).FirstOrDefault();
if (companyDetails.useZeroGspPath.Value || feedProduct.GuaranteedSalePrice > 0) // kab: 2010.04.07 - new rules...
PopulateProduct(feedProduct, localProduct, companyDetails);
}
}
else
{
if (companyDetails.useZeroGspPath.Value || localProduct.LowestPrice > 0) // kab: 2010.04.07 - new rules...
PopulateProduct(localProduct, companyDetails);
}
}
}
}
}
private void PopulateProduct(RivWorks.Model.Entities.Product product, RivWorks.Model.Entities.vwCompanyDetails RivCompany)
{
this.ProductID = product.ProductId;
if (product.alternateProductID != null)
this.alternateProductID = product.alternateProductID.Value;
this.BackgroundColor = product.BackgroundColor;
...
}
private void PopulateProduct(RivWorks.Model.Entities.AutoWithImage feedProduct, RivWorks.Model.Entities.Product rivProduct, RivWorks.Model.Entities.vwCompanyDetails RivCompany)
{
this.alternateProductID = feedProduct.AutoID;
this.BackgroundColor = Helpers.Product.GetCorrectValue(RivCompany.defaultBackgroundColor, rivProduct.BackgroundColor);
...
}
#endregion
#region IProduct Members
public Guid ProductID { get; set; }
public long alternateProductID { get; set; }
public Guid CompanyId { get; set; }
...
#endregion
}
}
다른 수업에서는 다음이 있습니다.
using dto = RivWorks.DTO;
using contracts = RivWorks.Interfaces.DataContracts;
...
public static List<contracts.IProduct> Get(Guid companyID)
{
List<contracts.IProduct> myList = new List<dto.Product>();
...
왜 이런 일이 일어날 지 아이디어가 있습니까? (그리고 나는 그것이 사소한 일이라고 확신합니다!)
답변
네, C #의 공분산 제한입니다. 한 유형의 목록을 다른 목록으로 변환 할 수 없습니다.
대신에:
List<contracts.IProduct> myList = new List<dto.Product>();
당신은 이것을해야합니다
List<contracts.IProduct> myList = new List<contracts.IProduct>();
myList.Add(new dto.Product());
Eric Lippert가 이러한 방식으로 구현 한 이유를 설명합니다.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
(그리고 항목 배열 작업과 다른 이유).
답변
당신은 그렇게 할 수 없습니다. 가있는 경우 아무거나List<IProduct>
넣을 수 있습니다 . 따라서 구현 하는 것이 있으면 목록에 넣을 수 있습니다. 그러나 원래의 목록은 다음과 같이 생성 된 경우에만 기대 목록을 사용하는 모든 유형의 객체 있도록, 하지, 목록에 표시 할 수 있습니다. IProduct
Product2
IProduct
List<Product>
Product
Product2
당신은 변환 할 수 있도록 .NET 4.0, 그들은 인터페이스에 대한 공분산 및 contravariance 추가 IEnumerable<Product>
에 IEnumerable<IProduct>
. 그러나 이것은 여전히 목록에 대해서는 작동하지 않습니다. 목록 인터페이스를 통해 “물건을 넣거나” “물건을 꺼낼”수 있기 때문입니다.
답변
참고로 Generics의 Covariance 및 Contravariance 가 C # 4.0에 추가되었습니다.
답변
글쎄, 당신은 이것을 사용할 수 있습니다!
class A {}
class B : A {}
...
List<B> b = new List<B>();
...
List<A> a = new List<A>(b.ToArray());
이제 직접적인 해결책을 제공하기 위해
using dto = RivWorks.DTO;
using contracts = RivWorks.Interfaces.DataContracts;
...
public static List<contracts.IProduct> Get(Guid companyID) {
List<dto.Product> prodList = new List<dto.Product>();
...
return new List<contracts.IProduct>(prodList.ToArray());
}
답변
이것은 그것을 수행하는 방법에 대한 작은 예입니다.
public void CreateTallPeople()
{
var tallPeopleList = new List<IPerson>
{
new TallPerson {Height = 210, Name = "Stevo"},
new TallPerson {Height = 211, Name = "Johno"},
};
InteratePeople(tallPeopleList);
}
public void InteratePeople(List<IPerson> people)
{
foreach (var person in people)
{
Console.WriteLine($"{person.Name} is {person.Height}cm tall. ");
}
}
답변
대신 이것을 시도하십시오.
List<contracts.IProduct> myList = new List<contracts.IProduct>((new List<dto.Product>()).Cast<contracts.IProduct>());
답변
