C# 通用工厂法铸造问题
尝试创建工厂以返回通用接口(如下所示),但出现错误: 无法将C# 通用工厂法铸造问题,c#,generics,factory,C#,Generics,Factory,尝试创建工厂以返回通用接口(如下所示),但出现错误: 无法将IFinancialsSyncService隐式转换为IFinancialsSyncService。存在明文转换,是否缺少强制转换 但是,如果我显式地强制转换它,我会得到一个强制转换是冗余的错误以及第一个错误 return (IFinancialsSyncService<Vendor, QuickBooksVendor>)new QuickbooksVendorService(); 并将其替换为以下内容: var qbEn
IFinancialsSyncService
隐式转换为IFinancialsSyncService
。存在明文转换,是否缺少强制转换
但是,如果我显式地强制转换它,我会得到一个强制转换是冗余的
错误以及第一个错误
return (IFinancialsSyncService<Vendor, QuickBooksVendor>)new QuickbooksVendorService();
并将其替换为以下内容:
var qbEntityService = EntityServiceFactory.Create(enumDataElement);
这个工厂会是什么样子?这与利斯科夫的替代原理有关。假设您的泛型类型是接口的一个属性:
public class QuickbooksVendorService : IFinancialsSyncService<Vendor, QuickBooksVendor>
public interface IFinancials { }
public interface IFinancialsSyncService
{
IFinancials Financials { get; set; }
}
现在我们实现以下接口:
public class Financials : IFinancials {}
public class FinancialsSyncService : IFinancialSyncService
{
public Financials Financials { get; set; }
}
这将导致编译器错误:
编译错误:“Program.FinancialSyncService”未实现接口成员“Program.IFinancialsSyncService.Financials”Program.FinancialSyncService.Financials无法实现Program.IFinancialsSyncService.Financials,因为它没有匹配的返回类型“Program.IFinancials”
这两个问题都有相同的问题。在我的示例中,接口声明结果的类型为IFinancials
,但它是更具体的派生类型Financials
,即使放置在属性中的任何有效值满足接口,它不能替换为从IFinancials
派生的任何值,只能替换为从Financials
派生的类型
因此,如果您的代码看起来像:
public interface IFinancialsSyncService<TEntity>
where TEntity : IEntity
{
TEntity Financials { get; set; }
}
公共接口IFinancialsSyncService
其中tenty:tenty
{
TEntity Financials{get;set;}
}
然后创建一个类:
public class QuickbooksVendorService : IFinancialSyncService<Vendor>
{
public Vendor Financials { get; set; }
}
公共类QuickbooksVendorService:IFinancialSyncService
{
公共供应商财务{get;set;}
}
但是,现在
QuickbooksVendorService
是IFinancialSyncService
而不是IFinancialSyncService
,因为该属性是派生类型。即使您没有此特定属性,它仍然会导致相同的问题,即泛型类型比接口更具体。使用工厂方法和适配器模式
switch (enumDataElement)
{
//Export jobs
case DataElement.Item:
var itemService = new QuickbooksItemService();
exportResult = itemService.UpdateMozzoEntityWithFinancialsId(session, response, EntityId, intUserId);
break;
case DataElement.Vendor:
var VendorService = new QuickbooksVendorService();
exportResult = UpdateMozzoEntityWithFinancialsId(new QuickbooksVendorService(),session, response, EntityId, intUserId);
break;
case DataElement.Bill:
var billService = new QuickbooksBillService();
exportResult = billService.UpdateMozzoEntityWithFinancialsId(session, response, intUserId);
break;
case DataElement.PurchaseOrder:
var qbPOService = new QuickbooksPurchaseOrderService();
exportResult = qbPOService.UpdateMozzoEntityWithFinancialsId(session, response, intUserId);
break;
case DataElement.SalesReceipt:
var salesReceiptService = new QuickbooksSalesReceiptService();
exportResult = salesReceiptService.UpdateStratusEntityWithFinancialsId(session, response, intUserId);
break;
}
[TestFixture]
public class Class1
{
[Test]
public void Go()
{
var qbItem = Export(1);
var qbVendor= Export(2);
var qbSales= Export(3);
}
public qbEntityService Export(int number)
{
var qb = Class1.Create(number);
return qb.UpdateMozzoEntityWithFinancialsId();
}
public static IEntityService Create(int enumDataElement)
{
switch (enumDataElement)
{
case 1:
return new QuickbooksItemService();
case 2:
return new QuickbooksVendorService();
case 3:
return new QuickbooksSalesReceiptServiceAdapter(new QuickbooksSalesReceiptService());
default:
throw new Exception();
}
}
}
public interface IEntityService
{
qbEntityService UpdateMozzoEntityWithFinancialsId();
}
public class qbEntityService
{
}
public class QuickbooksItemService : IEntityService
{
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksItemService, performing UpdateMozzoEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksVendorService : IEntityService
{
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksVendorService, performing UpdateMozzoEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksSalesReceiptService
{
public qbEntityService UpdateStratusEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksSalesReceiptService, performing UpdateStratusEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksSalesReceiptServiceAdapter : IEntityService
{
private QuickbooksSalesReceiptService adaptee;
public QuickbooksSalesReceiptServiceAdapter(QuickbooksSalesReceiptService adaptee)
{
this.adaptee = adaptee;
}
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
return adaptee.UpdateStratusEntityWithFinancialsId();
}
}
什么是供应商类型?它是否实现了智能?请检查QuickBooksVendor服务是否正确实现了IFinancialsSyncService。同时签入您的泛型方法TEntity实现IEntity和IFinancials,TQuickBooksEntity实现IQuickBooksEntity。@maxspan是的,它们都实现了正确的接口。谢谢Erik,因此您无法返回更具体的类型。我还有一些其他与实体相关的服务,类似于
QuickBooksVendorService
,它们都符合相同的接口。我正在寻找一个工厂,根据输入类型返回正确的一个。我只需要使用两种方法,它们都是通用的,都是接口定义的一部分。那么,我如何创建一个工厂来返回这些服务中的一项……工厂的常见返回类型是什么?还是我走错了路?注意,已更新的问题显示了我试图消除的内容。我想问您为什么要返回通用接口InterfaceOf
,而不仅仅是接口Interface
。你没有说谁在使用结果,所以很难知道。是的,我能够从接口中删除返回tenty
和TQuickBooksEntity
的方法,并删除接口的那些限定符。工厂工作正常,然后只返回接口IFinancialSyncService
。但是我想将这些方法恢复到接口。主要原因是,由于这是一个适配器类型的项目,它正在检索QuickBooks实体,如发票,然后将其转换为我们应用程序版本的发票,然后导入我们的应用程序数据库。@ChadRichardson您需要修复第59行和第62行。@ChadRichardson删除了更多未使用的泛型。
[TestFixture]
public class Class1
{
[Test]
public void Go()
{
var qbItem = Export(1);
var qbVendor= Export(2);
var qbSales= Export(3);
}
public qbEntityService Export(int number)
{
var qb = Class1.Create(number);
return qb.UpdateMozzoEntityWithFinancialsId();
}
public static IEntityService Create(int enumDataElement)
{
switch (enumDataElement)
{
case 1:
return new QuickbooksItemService();
case 2:
return new QuickbooksVendorService();
case 3:
return new QuickbooksSalesReceiptServiceAdapter(new QuickbooksSalesReceiptService());
default:
throw new Exception();
}
}
}
public interface IEntityService
{
qbEntityService UpdateMozzoEntityWithFinancialsId();
}
public class qbEntityService
{
}
public class QuickbooksItemService : IEntityService
{
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksItemService, performing UpdateMozzoEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksVendorService : IEntityService
{
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksVendorService, performing UpdateMozzoEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksSalesReceiptService
{
public qbEntityService UpdateStratusEntityWithFinancialsId()
{
Console.WriteLine("I am QuickbooksSalesReceiptService, performing UpdateStratusEntityWithFinancialsId");
return new qbEntityService();
}
}
public class QuickbooksSalesReceiptServiceAdapter : IEntityService
{
private QuickbooksSalesReceiptService adaptee;
public QuickbooksSalesReceiptServiceAdapter(QuickbooksSalesReceiptService adaptee)
{
this.adaptee = adaptee;
}
public qbEntityService UpdateMozzoEntityWithFinancialsId()
{
return adaptee.UpdateStratusEntityWithFinancialsId();
}
}