2009-11-01 27 views
1

我正在尝试编写一个审计日志方法,该方法将记录Linq-To-Sql模型中的所有更改。如何将未知类型传递给函数?

我想通过每种类型的更改获取所有更改循环调用我的方法,该方法为每种类型的对象创建日志记录。

我不确定这是否可能。

这是我的代码。当我尝试传入类型为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); 

    } 

是否有可能这样做?如果是这样,关于如何去做这件事的任何提示?

+0

在java中,所有东西都从Object类扩展而来,我不知道这是否是一种好方法,或者即使C#支持这一点,但是您可以在typeof(Object)中发送吗?一个单纯的建议,可能不是一个答案。 – 2009-11-01 18:20:17

回答

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 }); 

+0

谢谢乔。太棒了! – littlechris 2009-11-01 18:57:03

0

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

2

致电GetType原始而不是尝试使用typeof来获取其类型。

0

根本不需要指定类型。类型推断会为你做。只需调用没有类型参数的方法:AuditLogger.GetAuditLogRecord(original, update, "Update", "", userName);

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

0

如果我正确理解你的问题,你正尝试在异构对象集合上使用var和typeof()。 typeof()获得编译时类型,var也是编译时类型。但是,从您的代码片段看来,您需要运行时类型确定。正如另一个答案中提到的,GetType将为您提供特定于对象的运行时类型,但不能在GetAuditLogRecord的通用声明中使用它。

所以从某种意义上说,你最好坚持使用object作为你的类型,至少直到你进入GetAuditLogRecord方法。

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

0

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

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对象并不需要知道更多关于它正在审计的对象的实现细节。

相关问题