我正在嘗試實作一些通用配置型別,但遇到了轉換問題。理想情況下,我想要的是一個強型別的配置值實體,可以分配給我們不同的匯出器。
我所擁有的是:
IConfigurableExport:將匯出器標記為可配置并包含ICollection<IExportConfiguration<Object>> Configurations屬性的介面IExportConfiguration<T>: 定義通用屬性(名稱、描述等)的介面ExportConfiguration<T>:實作的抽象類IExportConfiguration<T>,將介面屬性設定為抽象,添加一些常用功能,例如從配置值串列中設定自身的值等等ConfigurationInstance<bool>: 繼承ExporterConfiguration<Boolean>
用于配置匯出器的 UI 是基于 IConfigurableExport.Configurations 中的值動態構建的。當我嘗試呼叫 IConfigurableExport.Configurations 時,出現轉換錯誤。下面是一些示例代碼來說明問題:
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var t = new MyExporter();
var configs = t.Configurations;
foreach(var conf in configs){
Console.WriteLine(conf.Name);
}
}
}
public interface IExportConfiguration<T>{
string Description {get;}
Guid Id {get;}
string Name {get;}
T Value {get; set;}
}
public abstract class ExportConfiguration<T>
: IExportConfiguration<T>
{
public abstract string Description { get; }
public abstract string Name { get; }
public abstract Guid Id { get; }
public abstract T Value { get; set; }
public abstract T DefaultValue { get; set; }
public virtual void SetValue(ICollection<KeyValuePair<Guid, object>> values)
{
if (values.Any(kvp => kvp.Key == this.Id))
Value = (T)values.First(kvp => kvp.Key == this.Id).Value;
else
Value = this.DefaultValue == null ? this.DefaultValue : default(T);
}
}
public interface IConfigurableExport {
ICollection<IExportConfiguration<object>> Configurations {get;}
}
public class MyConfig : ExportConfiguration<bool> {
public override string Description { get { return "This is my description"; }}
public override string Name { get{ return "My Config Name"; }}
public override Guid Id { get { return Guid.Parse("b6a9b81d-412d-4aa8-9090-37c9deb1a9f4"); }}
public override bool Value { get; set;}
public override bool DefaultValue { get; set;}
}
public class MyExporter : IConfigurableExport {
MyConfig conf = new MyConfig();
public ICollection<IExportConfiguration<object>> Configurations {
get {
return new List<IExportConfiguration<object>> { (IExportConfiguration<object>)conf };
}
}
}
這是一個 dontnetfiddle來說明這個問題
uj5u.com熱心網友回復:
主要問題是IExportConfiguration<T>定義了一個T Value {get; set;}
如果您有IExportConfiguration<bool>,則無法IExportConfiguration<bool>轉換為 ,IExportConfiguration<object>因為您無法設定Value為 型別object,則必須將其設定為型別bool才能使其型別安全。
為了能夠進行這種型別的轉換,您需要使用如下所示的協變介面
public interface IExportConfiguration<T> : IReadOnlyExportConfiguration<T>{
new T Value {get; set;}
}
//this interface is covariant, and if you have a IReadOnlyExportConfiguration<string>
//it can be cast to an IReadOnlyExportConfiguration<object>
public interface IReadOnlyExportConfiguration<out T>{
string Description {get;}
Guid Id {get;}
string Name {get;}
T Value {get;}
}
然后您可以將您的可配置匯出重新定義為
public interface IConfigurableExport {
ICollection<IReadOnlyExportConfiguration<object>> Configurations {get;}
}
但是你不能MyConfig用作 bool 配置,因為IReadOnlyExportConfiguration<bool>不會強制轉換,IReadOnlyExportConfiguration<object>因為 bool 是一種簡單的資料型別。T 的型別必須是型別別才能與 協變object。
public class MyConfig : ExportConfiguration<string> {
public override string Description { get { return "This is my description"; }}
public override string Name { get{ return "My Config Name"; }}
public override Guid Id { get { return Guid.Parse("b6a9b81d-412d-4aa8-9090-37c9deb1a9f4"); }}
public override string Value { get; set;}
public override string DefaultValue { get; set;}
}
然后最后你的出口商變成
public class MyExporter : IConfigurableExport {
MyConfig conf = new MyConfig();
public ICollection<IReadOnlyExportConfiguration<object>> Configurations {
get {
return new List<IReadOnlyExportConfiguration<object>> { (IReadOnlyExportConfiguration<object>)conf };
}
}
}
但此時您將無法為您的配置設定值,如果需要,您將需要重新構建您的解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/355966.html
