如何将未知类型传递给函数?

时间:2009-11-01 18:13:54

标签: c# linq-to-sql

我正在尝试编写一个审核日志方法,该方法将记录Linq-To-Sql模型中的所有更改。

我想让所有更改成为每种类型的更改的循环,调用my方法为每种类型的对象创建日志记录。

我不确定这是否可能。

这是我的代码。当我尝试将类型传递给typeof(原始)时,我得到一个错误我在设计时不知道类型,因为它可以是我模型中的任何linq对象。

    ChangeSet changedObjects = this._lmsDb.GetChangeSet();

    foreach (var update in changedObjects.Updates)
    {

        Type type = update.GetType();
        var original = this._lmsDb.GetTable(type).GetOriginalEntityState(update);
        // Error from <typeof(original)>
        AuditLog au = AuditLogger.GetAuditLogRecord<typeof(original)>(original, update, "Update", "", userName);

        this._lmsDb.AuditLogs.InsertOnSubmit(au);

    }

有可能这样做吗?如果有的话,有关如何解决这个问题的任何提示吗?

7 个答案:

答案 0 :(得分:2)

原始上调用GetType,而不是尝试使用typeof来获取其类型。

答案 1 :(得分:1)

反思怎么样?:

MethodInfo mi = typeof(AuditLogger).GetMethod("GetAuditLogRecord");
Type[] genericArguments = new Type[] { original.GetType() };
MethodInfo genericMI = mi.MakeGenericMethod(genericArguments);
AuditLog au = 
    (AuditLog)genericMI.Invoke(
        null, new object[] { original, update, "", userName });

答案 2 :(得分:0)

你可以只使用一个Object作为函数接受的类型......你的函数定义目前是什么样的?

答案 3 :(得分:0)

您根本不需要指定类型。类型推断将为您完成。只需调用不带类型参数的方法:AuditLogger.GetAuditLogRecord(original, update, "Update", "", userName);

另请注意,var根本不是未知类型。有一个特定的类型,编译器知道它是什么,否则它会抱怨你对变量的赋值。在Visual Studio中,如果将鼠标悬停在var关键字上,IDE将告诉您类型。

答案 4 :(得分:0)

如果我正确理解了您的问题,那么您尝试在异构的对象集合上使用var和typeof()。 typeof()获取编译时类型,var也是编译时键入。但是,从您的代码段开始,您似乎需要运行时类型确定。正如另一个答案中所提到的,GetType将为您提供特定于对象的运行时类型,但您不能在GetAuditLogRecord的泛型声明中使用它。

所以从某种意义上说,你最好坚持使用对象作为你的类型,至少在你进入GetAuditLogRecord方法之前。

我不知道对象的来源是什么。如果这些是生成的代码(从LINQ到SQL或实体框架,或其他一些工具),请查看是否有方法可以利用部分类或部分方法实现来处理您的审计要求。您还可以设置一个所有这些对象继承的抽象类,它至少实现部分审计要求。

答案 5 :(得分:0)

如果您不知道该类型使用对象!

答案 6 :(得分:0)

如果GetAuditLogRecord是通用方法,则不必在编译时指定它使用的类型 - 也就是说,首先,为什么要首先使用泛型方法:

static void Main(string[] arguments)
{
    int i = 0;
    string s = "";
    Test(i);
    Test(s);
    Console.ReadLine();
}

static void Test<T>(T arg)
{
    Console.WriteLine(arg.GetType());
}

产生

System.Int32
System.String

请注意,我的示例不一定是通用方法;它可以采用object类型的参数并仍然有效。如果方法使用类型参数创建新变量,则只需要是通用的。

我怀疑你实际上是否会在这里尝试使用泛型。在你所描述的设计中,我希望GetAuditLog会有这样的签名:

AuditLogRecord GetAuditLog(IAuditable original, IAuditable current, AuditAction action, User user)

...其中IAuditable公开AuditLogRecord需要的属性/方法,AuditAction是枚举。 IAuditable可能如下所示:

interface IAuditable
{
   List<KeyValuePair<string, object>> AuditableProperties;
}

因此,任何可以审计的对象都负责显示其更改与审计日志相关的属性名称/值的列表,AuditLogRecord对象不需要了解有关实现的更多信息它正在审计的对象的细节。