我有一个通用的类。 Class<T>
并且根据调用代码中的switch语句,它可以是class<int>
class<string>
class<decimal>
返回此方法会将其作为对象返回,因为调用代码在设置之前不知道它是什么。
一旦我从函数中取回对象,有没有办法做到这一点?
load(object result)
{
Type t = result.GetType().GetGenericArguments()[0];
Class<t> x = (Class<t>) result;
}
或者我是否必须设置检查以检查每种类型。如果int
然后Class<int>
等等......
编辑:
以下是我要做的,实际代码:
public class ReportResult<TP>
{
public ReportResult()
{
ReportHeaders = new List<ReportHeader>();
ReportViews = new List<IDataAttributeChild<TP>>();
}
public List<ReportHeader> ReportHeaders {get;set;}
public List<IDataAttributeChild<TP>> ReportViews {get;set;}
}
BAL
public object GetReportData(ReportProcedureNameEventArg procedureNameEventArg)
{
object result = null;
switch (procedureNameEventArg.SelectedNode.Class)
{
case ReportClass.Count:
var r = new ReportResult<int>
{
ReportViews = GetCountByReport(procedureNameEventArg),
ReportHeaders = GetReportHeaders(procedureNameEventArg.SelectedNode.ReportViewId)
};
result = r;
break;
case ReportClass.List:
break;
case ReportClass.Date:
var r = new ReportResult<datetime>
{
ReportViews = GetDateSummaryReport(procedureNameEventArg),
ReportHeaders = GetReportHeaders(procedureNameEventArg.SelectedNode.ReportViewId)
};
result = r;
break;
default:
throw new ArgumentOutOfRangeException();
}
return result;
}
GUI
public void LoadTreeResult(object result)
{
Type t = result.GetType().GetGenericArguments()[0];
ReportResult<?> fff = (ReportResult<?>)result;
dgResult.Columns.Clear();
foreach (var header in result.ReportHeaders)
{
dgResult.Columns.Add(
new DataGridTextColumn
{
Header = header.Header,
Binding = new Binding(header.Binding)
});
}
// This would also be a switch depending on a property coming
// back to now what class to cast to in order to populate the grid.
List<ReportCountByView> d = new List<ReportCountByView>();
foreach (var reportCountByView in result.ReportViews)
{
d.Add((ReportCountByView)reportCountByView);
}
dgResult.ItemsSource = d;
}
这是类模型的布局,以防它可能有所帮助。
感谢。
答案 0 :(得分:3)
如果要在解析后对实例'x'调用相同的操作,可以考虑使用接口,这将允许您定义对象执行的方法(和属性)而不定义它的类型。
您的代码最终可能会看起来像这样
public interface IMyInterface
{
void PerformOperation();
}
public class MyGeneric<T> : IMyInterface
{
T Value {get;set;}
MyGeneric(T val)
{
Value = val;
}
void PerformOperation
{
Console.WriteLine("T is {0}", typeof(T));
Console.WriteLine("Value is {0}", Value);
}
}
public void main(string[] args)
{
IMyInterface inst = null;
switch (args[0])
{
case "string":
inst = new MyGeneric("hello");
break;
case "int":
inst = new MyGeneric(7);
break;
case "decimal"
inst = new MyGeneric(18.9M);
break;
}
inst.PerformOperation();
}
答案 1 :(得分:1)
以后你想用x做什么?此外,如果您可以构建它以使x始终是某个基类的实例,则可以将其强制转换为基类。
答案 2 :(得分:1)
这取决于您以后打算如何使用泛型类型。 string
,int
和decimal
除了object
之外没有共同的基本类型,但是它们共享一些接口,因此您可以选择类似Class<IComparable>
的内容你想稍后对它们进行排序。或者,如果要使用多个接口,则可以声明泛型约束:
Class<T> where T : IEquatable<T>, IComparable<T>, IFormattable // and so on...
但是你似乎要求的东西似乎不可能。泛型的整个前提是在设计时设置类型。
答案 3 :(得分:0)
我的意见
如果结果始终用于调用类的相同成员,则可以创建一个接口并将其实现到不同的类,并将结果作为接口。 这样,您就可以使用不同的类,但是在这些类中实现的接口的一些相同成员
答案 4 :(得分:0)
我认为执行此切换的最佳方法是实际为不同类型实现单独的方法,并在UI层切换。
例如
public ReportResult<int> GetReportDataCount(ReportProcedureNameEventArg procedureNameEventArg)
public ReportResult<DateTime> GetReportDataDate(ReportProcedureNameEventArg procedureNameEventArg)
public void GetReportDataList(ReportProcedureNameEventArg procedureNameEventArg)
“List”是一个真正抛弃我的,因为它返回null,否则我会说做类似的事情
public ReportResult<T> GetReportData<T>(ReportProcedureNameEventArg procedureNameEventArg) where T:struct
(然后以编程方式强制执行类型)。
如果你想用动态尝试它,我认为你可以通过使用ReportResult进行鸭子打字来实现这种方式,但是混合中的列表模式也可能会变得混乱。