gpt4 book ai didi

C# 通用接口(interface)和工厂模式

转载 作者:可可西里 更新时间:2023-11-01 08:17:34 26 4
gpt4 key购买 nike

我正在尝试创建一个通用接口(interface),其中一个方法的参数类型由通用定义

编辑

在意识到我可能通过在 Factory 创建方法中指定类型参数混淆了问题后,我稍微更改了问题。我所拥有的是我需要对第 3 方 API 进行的两种类型的 API 调用。第一个使用 int 类型的 Id 从 API 检索记录。第二个也从 API 检索记录,但 Id 是一个字符串 (guid)。我为每种记录类型(ClientEntity 和 InvoiceEntity)都有一个类,它们都实现了一个通用接口(interface),我在其中传入了 Id 类型

这是我在其中声明一个带有 id 参数的方法的接口(interface)

public interface IGeneric<TId>
{
void ProcessEntity(TId id);
}

我在几个类中实现了接口(interface),一个将 id 设置为 int,另一个设置为字符串。

public class ClientEntity: IGeneric<int> // Record with Id that is an int
{
public void ProcessEntity(int id)
{
Console.WriteLine(id);
// call 3rd party API with int Id
}
}

public class InvoiceEntity: IGeneric<string> // Record with Id that is a string (guid)
{
public void ProcessEntity(string id)
{
Console.WriteLine(id);
// call 3rd party API with string Id
}
}

我想知道的是如何在工厂模式中使用它?

public static class GenericFactory
{
public static IGeneric<WhatGoesHere> CreateGeneric(string recordType)
{
if (recordType == "Client")
{
return new ClientEntity();
}
if (type == "Invoice")
{
return new InvoiceEntity();
}

return null;
}

}

目标是使用工厂实例化正确的类,以便我可以调用 ProcessEntity 方法

编辑

我不想将通用类型传递给工厂方法,因为工厂创建的类应该处理它。当我创建对象时,我不知道需要什么 Id 类型,我希望工厂处理那个

例如

   var myGeneric = GenericFactory.CreateGeneric("Client");
myGeneric.ProcessEntity("guid")

   var myGeneric = GenericFactory.CreateGeneric("Invoice");
myGeneric.ProcessEntity(1234)

我希望这是有道理的

最佳答案

你应该能够做这样的事情:

public static class GenericFactory
{
public static IGeneric<T> CreateGeneric<T>()
{
if (typeof(T) == typeof(string))
{
return (IGeneric<T>) new GenericString();
}

if (typeof(T) == typeof(int))
{
return (IGeneric<T>) new GenericInt();
}

throw new InvalidOperationException();
}
}

你会像这样使用它:

var a = GenericFactory.CreateGeneric<string>();
var b = GenericFactory.CreateGeneric<int>();

请注意,这使用强类型调用而不是将类型名称作为字符串传递(这可能是也可能不是您真正想要的)。


如果你想为类型名称传递一个字符串,你将不得不返回一个object,因为没有办法返回实际的类型:

public static object CreateGeneric(string type)
{
switch (type)
{
case "string": return new GenericString();
case "int": return new GenericInt();
default: throw new InvalidOperationException("Invalid type specified.");
}
}

显然,如果您有一个对象,您通常必须将其转换为正确的类型才能使用它(这需要您知道实际类型)。

或者,您可以使用反射来确定它包含哪些方法,并以这种方式调用它们。但是您仍然需要知道类型才能传递正确类型的参数。

我认为你在这里尝试做的不是正确的方法,一旦你开始尝试使用它你就会发现。

Hacky 解决方案:使用dynamic

不过,有一种方法可以获得接近您想要的东西:使用 dynamic 如下(假设您使用的是 object CreateGeneric(string type)上面的工厂方法):

dynamic a = GenericFactory.CreateGeneric("string");
dynamic b = GenericFactory.CreateGeneric("int");

a.ProcessEntity("A string");
b.ProcessEntity(12345);

请注意,dynamic 在后台使用反射和代码生成,这会使初始调用相对较慢。

另请注意,如果您将错误的类型传递给通过 dynamic 访问的方法,您将得到一个讨厌的运行时异常:

dynamic a = GenericFactory.CreateGeneric("string");
a.ProcessEntity(12345); // Wrong parameter type!

如果您运行该代码,您会得到这种运行时异常:

Unhandled Exception: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'ConsoleApplication1.GenericString.ProcessEntity(string)' has some invalid arguments
at CallSite.Target(Closure , CallSite , Object , Int32 )
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2[T0,T1](CallSite site, T0 arg0, T1 arg1)
at ConsoleApplication1.Program.Main() in D:\Test\CS6\ConsoleApplication1\Program.cs:line 71

关于C# 通用接口(interface)和工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39386586/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com