C#铸造和仿制药
我一直在与一段C代码作斗争,尽管我已经找到了解决问题的方法,但它绝不是理想的(请参见下面的DoSomething_WorksButNotIdeal()) 我想做的是,不使用if,else语句(根据我想要支持的类型,它可能非常庞大),而是使用泛型转换,但我无法让它工作。我尝试在DoSomething_HelpMe()方法中演示这一点 有没有办法做到这一点?非常感谢您的帮助C#铸造和仿制药,c#,generics,casting,C#,Generics,Casting,我一直在与一段C代码作斗争,尽管我已经找到了解决问题的方法,但它绝不是理想的(请参见下面的DoSomething_WorksButNotIdeal()) 我想做的是,不使用if,else语句(根据我想要支持的类型,它可能非常庞大),而是使用泛型转换,但我无法让它工作。我尝试在DoSomething_HelpMe()方法中演示这一点 有没有办法做到这一点?非常感谢您的帮助 public interface ITag { string TagName { get; } Type Ty
public interface ITag
{
string TagName { get; }
Type Type { get; }
}
public interface ITag<T> : ITag
{
T InMemValue { get; set; }
T OnDiscValue { get; set; }
}
public class Tag<T> : ITag<T>
{
public Tag(string tagName)
{
TagName = tagName;
}
public string TagName { get; private set; }
public T InMemValue { get; set; }
public T OnDiscValue { get; set; }
public Type Type{ get{ return typeof(T);} }
}
public class MusicTrack
{
public MusicTrack()
{
TrackTitle = new Tag<string>("TrackTitle");
TrackNumber = new Tag<int>("TrackNumber");
Tags = new Dictionary<string, ITag>();
Tags.Add(TrackTitle.TagName, TrackTitle);
Tags.Add(TrackNumber.TagName, TrackNumber);
}
public IDictionary<string,ITag> Tags;
public ITag<string> TrackTitle { get; set; }
public ITag<int> TrackNumber { get; set; }
}
public static class Main
{
public static void DoSomething_WorksButNotIdeal()
{
MusicTrack track1 = new MusicTrack();
MusicTrack track2 = new MusicTrack();
// Set some values on the tracks
foreach (ITag tag in track1.Tags.Values)
{
Type type = tag.Type;
if (type == typeof(string))
{
((ITag<string>) tag).InMemValue = ((ITag<string>)track2.Tags[tag.TagName]).OnDiscValue;
}
else if (type == typeof(int))
{
((ITag<int>)tag).InMemValue = ((ITag<int>)track2.Tags[tag.TagName]).OnDiscValue;
}
else if (type == typeof(bool))
{
((ITag<bool>)tag).InMemValue = ((ITag<bool>)track2.Tags[tag.TagName]).OnDiscValue;
}
// etc etc
else
{
throw new Exception("Unsupported type.");
}
}
}
public static void DoSomething_HelpMe()
{
MusicTrack track1 = new MusicTrack();
MusicTrack track2 = new MusicTrack();
// Set some values on the tracks
foreach (ITag tag in track1.Tags.Values)
{
Type type = tag.Type;
// THIS OBVIOUSLY DOESN'T WORK BUT I'M JUST TRYING TO DEMONSTRATE WHAT
// I'D IDEALLY LIKE TO ACHIEVE
((ITag<typeof(type)>)tag).InMemValue = ((ITag<typeof(type)>)track2.Tags[tag.TagName]).OnDiscValue;
}
}
}
公共接口ITag
{
字符串标记名{get;}
类型{get;}
}
公共接口ITag:ITag
{
tinmemvalue{get;set;}
T OnDiscValue{get;set;}
}
公共类标记:ITag
{
公共标记(字符串标记名)
{
标记名=标记名;
}
公共字符串标记名{get;private set;}
公共T InMemValue{get;set;}
公共tOnDiscValue{get;set;}
公共类型类型{get{return typeof(T);}
}
公共类MusicTrack
{
公共音乐频道()
{
TrackTitle=新标签(“TrackTitle”);
TrackNumber=新标签(“TrackNumber”);
Tags=newdictionary();
Tags.Add(TrackTitle.TagName,TrackTitle);
Tags.Add(TrackNumber.TagName,TrackNumber);
}
公共词典标签;
公共ITag TrackTitle{get;set;}
公共ITag轨道号{get;set;}
}
公共静态类主
{
公共静态无效剂量(工作但不理想)()
{
MusicTrack track1=新的MusicTrack();
MusicTrack track2=新的MusicTrack();
//在轨迹上设置一些值
foreach(track1.Tags.Values中的ITag标记)
{
Type=tag.Type;
if(type==typeof(string))
{
((ITag)tag).InMemValue=((ITag)track2.Tags[tag.TagName]).OnDiscValue;
}
else if(type==typeof(int))
{
((ITag)tag).InMemValue=((ITag)track2.Tags[tag.TagName]).OnDiscValue;
}
else if(type==typeof(bool))
{
((ITag)tag).InMemValue=((ITag)track2.Tags[tag.TagName]).OnDiscValue;
}
//等等
其他的
{
抛出新异常(“不支持的类型”);
}
}
}
公共静态无效DoSomething_HelpMe()
{
MusicTrack track1=新的MusicTrack();
MusicTrack track2=新的MusicTrack();
//在轨迹上设置一些值
foreach(track1.Tags.Values中的ITag标记)
{
Type=tag.Type;
//这显然不起作用,但我只是想证明一下
//理想情况下,我希望实现
((ITag)tag).InMemValue=((ITag)track2.Tags[tag.TagName]).OnDiscValue;
}
}
}
您不能拥有的任何理由:
public interface ITag
{
string TagName { get; }
Type Type { get; }
object InMemValue { get; set; }
object OnDiscValue { get; set; }
}
并使用ITag
使其更具体
public interface ITag<T> : ITag
{
new T InMemValue { get; set; }
new T OnDiscValue { get; set; }
}
(编辑) 另一个选项是非通用
ITag
上的方法:
void CopyValueFrom(ITag tag);
(可能会更具体地说明它复制到/从中复制的内容)
您的具体实现(Tag
)必须假设ITag
实际上是一个ITag
并强制转换:
public void CopyFromTag(ITag tag) {
ITag<T> from = tag as ITag<T>;
if(from==null) throw new ArgumentException("tag");
this.TheFirstProperty = from.TheSecondProperty;
}
public void CopyFromTag(ITag标记){
ITag from=标记为ITag;
如果(from==null)抛出新的ArgumentException(“标记”);
this.TheFirstProperty=from.TheSecondProperty;
}
解决此问题的最简单方法是解析包含信息的类型,即标记
实现中的类型,因此将以下内容添加到现有类型中(仅显示添加内容!)
这里有一种方法,它需要大量的样板文件,但允许您使用现有的
ITag
、ITag
和Tag
定义来做您想做的事情。TagSetter
类以类型安全的方式为任何ITag
设置来自光盘上值的内存中值
//
///允许使用任何类型的标记来获取TResult类型的结果
///
///使用标记后的结果类型
公共接口ITagUser
{
t结果使用(ITag标签);
}
///
///允许使用任何类型的标记(无返回值)
///
公共接口ITagUser
{
无效使用(ITag标签);
}
///
///包装某个未知类型的标记。允许标记用户(带或不带返回值)使用包装列表。
///
公共接口
{
TResult Apply(ITagUser用户);
无效申请(ITagUser用户);
}
///
///包装T类型的标记,隐藏类型本身。
///
///标记中包含的元素的类型
类ExistsTag:IExistsTag
{
ITag标签;
公共出口(ITag标签)
{
this.tag=tag;
}
#地区成员
公共TResult应用(ITagUser用户)
{
返回用户使用(标签);
}
公开作废申请(ITagUser用户)
{
用户使用(标签);
}
#端区
}
公共接口ITag
{
字符串标记名{get;}
类型{get;}
}
公共接口ITag:ITag
{
tinmemvalue{get;set;}
T OnDiscValue{get;set;}
}
公共类标记:ITag
{
公共标记(字符串标记名)
{
标记名=标记名;
}
公共字符串标记名{get;private set;}
公共T InMemValue{get;set;}
公共tOnDiscValue{get;set;}
公共类型类型{get{return typeof(T);}
}
公共类标记设置器:ITagUser
{
#伊塔古斯区成员
公共无效使用(ITag标签)
{
tag.InMemValue=tag.OnDiscValue;
}
#端区
}
公共类标记提取器:ITagUser
{
#伊塔古斯区成员
公共ITag使用(ITag标签)
{
返回标签;
}
#端区
}
公共类MusicTrack
{
公共音乐频道()
{
TrackTitle=新标签(“TrackTitle”);
TrackNumber=新标签(“TrackNumber”);
Tags=newdictionary();
Tags.Add(TrackTitle.TagName,新的ExistsTag(TrackTitle));
Tags.Add(TrackNumber.TagName,新ExistsTag(TrackNumber
public void CopyFromTag(ITag tag) {
ITag<T> from = tag as ITag<T>;
if(from==null) throw new ArgumentException("tag");
this.TheFirstProperty = from.TheSecondProperty;
}
public interface ITag
{
void CopyFrom(bool sourceIsMem, ITag sourceTag, bool targetIsMem);
}
public class Tag<T> : ITag<T>
{
public void CopyFrom(bool sourceIsMem, ITag sourceTag, bool targetIsMem)
{
ITag<T> castSource = sourceTag as ITag<T>;
if (castSource == null)
throw new ArgumentException(
"Source tag is of an incompatible type", "sourceTag");
if (targetIsMem)
InMemValue = sourceIsMem ?
castSource.InMemValue : castSource.OnDiscValue;
else
OnDiscValue = sourceIsMem ?
castSource.InMemValue : castSource.OnDiscValue;
}
}
public static void DoSomething_HelpMe()
{
MusicTrack track1 = new MusicTrack();
MusicTrack track2 = new MusicTrack();
// Set some values on the tracks
foreach (ITag tag in track1.Tags.Values)
tag.CopyFrom(false, track2.Tags[tag.TagName], true);
}
/// <summary>
/// Allows a tag of any type to be used to get a result of type TResult
/// </summary>
/// <typeparam name="TResult">The result type after using the tag</typeparam>
public interface ITagUser<TResult>
{
TResult Use<T>(ITag<T> tag);
}
/// <summary>
/// Allows a tag of any type to be used (with no return value)
/// </summary>
public interface ITagUser
{
void Use<T>(ITag<T> tag);
}
/// <summary>
/// Wraps a tag of some unknown type. Allows tag users (either with or without return values) to use the wrapped list.
/// </summary>
public interface IExistsTag
{
TResult Apply<TResult>(ITagUser<TResult> user);
void Apply(ITagUser user);
}
/// <summary>
/// Wraps a tag of type T, hiding the type itself.
/// </summary>
/// <typeparam name="T">The type of element contained in the tag</typeparam>
class ExistsTag<T> : IExistsTag
{
ITag<T> tag;
public ExistsTag(ITag<T> tag)
{
this.tag = tag;
}
#region IExistsTag Members
public TResult Apply<TResult>(ITagUser<TResult> user)
{
return user.Use(tag);
}
public void Apply(ITagUser user)
{
user.Use(tag);
}
#endregion
}
public interface ITag
{
string TagName { get; }
Type Type { get; }
}
public interface ITag<T> : ITag
{
T InMemValue { get; set; }
T OnDiscValue { get; set; }
}
public class Tag<T> : ITag<T>
{
public Tag(string tagName)
{
TagName = tagName;
}
public string TagName { get; private set; }
public T InMemValue { get; set; }
public T OnDiscValue { get; set; }
public Type Type { get { return typeof(T); } }
}
public class TagSetter : ITagUser
{
#region ITagUser Members
public void Use<T>(ITag<T> tag)
{
tag.InMemValue = tag.OnDiscValue;
}
#endregion
}
public class TagExtractor : ITagUser<ITag>
{
#region ITagUser<ITag> Members
public ITag Use<T>(ITag<T> tag)
{
return tag;
}
#endregion
}
public class MusicTrack
{
public MusicTrack()
{
TrackTitle = new Tag<string>("TrackTitle");
TrackNumber = new Tag<int>("TrackNumber");
Tags = new Dictionary<string, IExistsTag>();
Tags.Add(TrackTitle.TagName, new ExistsTag<string>(TrackTitle));
Tags.Add(TrackNumber.TagName, new ExistsTag<int>(TrackNumber));
}
public IDictionary<string, IExistsTag> Tags;
public ITag<string> TrackTitle { get; set; }
public ITag<int> TrackNumber { get; set; }
}
public static class Main
{
public static void DoSomething_WorksButNotIdeal()
{
MusicTrack track1 = new MusicTrack();
MusicTrack track2 = new MusicTrack();
TagSetter setter = new TagSetter();
TagExtractor extractor = new TagExtractor();
// Set some values on the tracks
foreach (IExistsTag tag in track1.Tags.Values)
{
tag.Apply(setter);
// do stuff using base interface if necessary
ITag itag = tag.Apply(extractor);
}
}
}