[英]Avoid Casting in following Code by using Generics
I am new to generics and just wondering if it's possible to avoid the casting in the following code using better OO approach. 我是泛型的新手,只是想知道是否可以使用更好的OO方法避免在以下代码中进行转换。
public class CollectorFactory
{
public static MyCollector Create(ICredential credential)
{
return new MyCollector(credential);
}
}
public class MyCollector {
public MyCredential Credential { get; set; }
public MyCollector(ICredential credential)
{
this.Credential = (MyCredential)credential;
}
public void Show()
{
Console.WriteLine(this.Credential.Username);
Console.WriteLine(this.Credential.AuthToken);
}
}
public class MyCredential : ICredential
{
public string Username{ get; set; }
public string AuthToken { get; set; }
}
public interface ICredential
{
}
Is there a way to save the casting of ICredential to MyCredential in MyCollector's Constructor? 有没有办法在MyCollector的构造函数中保存ICredential到MyCredential的转换? I don't have option to put Username and AuthToken in ICredential as it's implemented by two different Credentials that both have different set of properties. 我没有选择将Username和AuthToken放在ICredential中,因为它是由两个具有不同属性集的不同凭据实现的。 CollectorFactory will be returning different MyCollector instances in the future and both need to have different credentials. CollectorFactory将来会返回不同的MyCollector实例,并且两者都需要具有不同的凭据。
Any help would be really appreciated. 任何帮助将非常感激。
我不认为你可以实现不同的凭证并尝试将它们用于ICredential。
Here is a way of doing this using generics. 这是使用泛型的方法。 Please read my comments in the code. 请在代码中阅读我的评论。
public class CollectorFactory<T>
{
public T Create(ICredential credential)
{
return (T)Activator.CreateInstance(typeof(T), credential);
}
}
public class MyCollector : BaseCollector
{
public dynamic Credential { get; private set; }
public MyCollector(ICredential credential)
: base(credential)
{
this.Credential = credential;
}
// Having this method here limits your ability to make it more generic.
// Consider moving this to MyCredential since it refers to specific properties in MyCredential.
// If that is not what you want, then you must do a type check before calling methods/ accessing props in Credentials.
public void Show()
{
Console.WriteLine(this.Credential.Username);
Console.WriteLine(this.Credential.AuthToken);
}
}
public class MyCredential : ICredential
{
public string Username { get; set; }
public string AuthToken { get; set; }
}
public abstract class BaseCollector : ICredentialCollector
{
protected BaseCollector(ICredential credential)
{
if (credential == null)
{
throw new ArgumentNullException(nameof(credential));
}
}
}
public interface ICredentialCollector
{
}
public interface ICredential
{
}
// test implementation
public class TestClass
{
public void AuthFactoryTest()
{
// test auth instance
MyCredential auth = new MyCredential() {AuthToken = "asfgasdgdfg", Username = "xuser"};
// Create test factory
var fact = new CollectorFactory<MyCollector>();
var myCollector = fact.Create(auth);
// Do what you need to do to collector object
myCollector.Show();
}
}
Generics isn't the solution in this case. 在这种情况下,泛型不是解决方案。 The issue here is that your factory is returning a specific type ( MyCollector
). 这里的问题是你的工厂正在返回一个特定的类型( MyCollector
)。 A solution around this would be the following: 解决此问题的解决方案如下:
public class CollectorFactory
{
public static ICollector Create(MyCredential credential)
{
return new MyCollector(credential);
}
public static ICollector Create(OtherCredential credential)
{
return new OtherCollector(credential);
}
}
public interface ICollector
{
void Show();
}
public class MyCollector : ICollector
{
public MyCredential Credential { get; set; }
public MyCollector(MyCredential credential)
{
this.Credential = credential;
}
public void Show()
{
Console.WriteLine(this.Credential.Username);
Console.WriteLine(this.Credential.AuthToken);
}
}
public class MyCredential : ICredential
{
public string Username{ get; set; }
public string AuthToken { get; set; }
}
public interface ICredential
{
}
The above is pretty much the canonical example of the Factory design pattern. 以上几乎是Factory设计模式的典型例子。
Instead of overloads you could also do typechecking in the factory: 您也可以在工厂中进行类型检查,而不是重载:
public class CollectorFactory
{
public static ICollector Create(ICredential credential)
{
if(credential.GetType() == typeof(MyCredential))
return new MyCollector((MyCredential) credential);
if(credential.GetType() == typeof(OtherCredential ))
return new OtherCollector((OtherCredential ) credential);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.