我正在编写一段通用代码,用于处理从多个来源加载数据的情况。我有一个方法,其签名如下:
public static TResult LoadFromAnySource<TContract, TSection, TResult>
(this TSection section,
string serviceBaseUri,
string nodeName)
where TSection : ConfigurationSection
where TResult : IDatabaseConfigurable<TContract, TSection>, new()
where TContract : new()
但这有些过度:当我传递 TResult
时,我已经知道 TContract
和 TSection
的确切含义。在我的示例中:
public interface ISourceObserverConfiguration
: IDatabaseConfigurable<SourceObserverContract, SourceObserverSection>
但是我必须写以下内容:
sourceObserverSection.LoadFromAnySource<SourceObserverContract,
SourceObserverSection,
SourceObserverConfiguration>
(_registrationServiceConfiguration.ServiceBaseUri, nodeName);
您可以看到,我必须两次指定
<SourceObserverContract, SourceObserverSection>
这对键值对,这违反了DRY原则。因此,我想写出类似以下的内容:sourceObserverSection.LoadFromAnySource<SourceObserverConfiguration>
(_registrationServiceConfiguration.ServiceBaseUri, nodeName);
使SourceObserverContract
和SourceObserverSection
从接口中推断出来。
C#中是否可能,还是我需要手动指定?
IDatabaseConfigurable
看起来像:
public interface IDatabaseConfigurable<in TContract, in TSection>
where TContract : ConfigContract
where TSection : ConfigurationSection
{
string RemoteName { get; }
void LoadFromContract(TContract contract);
void LoadFromSection(TSection section);
}
这个扩展程序根据一些逻辑调用这两个方法。我必须指定类型,因为我需要访问每个具体实现的属性,所以我需要协变性。
IDatabaseConfigurable<TContract, TSection> LoadFromAnySource(this TSection section, string serviceBaseUri, string nodeName, Func<TContract> contractCreator)
(或者只是TContract contract
),则类型可以从使用中推断出来。 - Jeroen Mosterttwitter
中三次写t
,对吧? :D 这两个并不相同——一个比另一个更加通用。无论如何,@JeroenMostert的评论几乎是最好的方法,并且应该完全成为一个答案。虽然可能更适合像程序员这样的地方,而不是SO——我真的不认为这是一个适合SO的好问题。 - LuaanFunc<IDatabaseConfigurable<...>>
。一个“有效”的结果是实现了该接口的结果--如果需要更多的东西,那么设计上就有问题了。(事实上,我相当确定设计上存在一些需要重构的问题,但这不是我们讨论的主题。) - Jeroen Mostert