我经常发现自己使用lambdas作为某种"本地功能",通过像以下那样的重复操作让我的生活变得更轻松:
Func<string, string> GetText = (resource) => this.resourceManager.GetString(resource);
Func<float, object, string> FormatF1 = (f, o) => String.Format("{0:F1} {1}", f, o);
Func<float, object, string> FormatF2 = (f, o) => String.Format("{0:F2} {1}", f, o);
Run Code Online (Sandbox Code Playgroud)
而不是一遍又一遍地编写String.Format-thing,我可以愉快地吹掉FormatF2,例如节省自己的时间,当我需要改变格式化的东西时,只有一个地方可以进行编辑.特别是当我只需要给定函数中的功能时,我非常不愿意将它们变成一个真正的函数.虽然上面的lambdas相对较小...有时我会有较大的那些(以下是应该将数据添加到表中以进行打印输出):
Action<string, string, string> AddSurfaceData = (resource, col, unit) => {
renderTable.Cells[tableRowIndex, 0].Text = "\t" + this.GetText(resource);
renderTable.Cells[tableRowIndex, 1].Text = FormatF2(paraHydReader.GetFloat(paraHydReader.GetOrdinal(col)), "");
renderTable.Cells[tableRowIndex, 1].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Right;
renderTable.Cells[tableRowIndex, 2].Text = " " + this.GetText(unit);
renderTable.Cells[tableRowIndex, 2].Style.TextAlignHorz = C1.C1Preview.AlignHorzEnum.Left;
++tableRowIndex;
};
Run Code Online (Sandbox Code Playgroud)
同样,我经常需要这个,上面的所有好处也适用.但是,正如你所看到的,这个对于lambda表达式来说很长.问题是:你什么时候画线?我的最后一个lambda太多了吗?还有什么其他方法(除了使用实际函数或尝试将数据填充到容器中并循环遍历它们)以避免一遍又一遍地编写相同的代码?
提前致谢
基督教
我想知道是否应该创建适用于对象级别的扩展方法,或者它们是否应该位于类层次结构中的较低点.我的意思是:
public static string SafeToString(this Object o) {
if (o == null || o is System.DBNull)
return "";
else {
if (o is string)
return (string)o;
else
return "";
}
}
public static int SafeToInt(this Object o) {
if (o == null || o is System.DBNull)
return 0;
else {
if (o.IsNumeric())
return Convert.ToInt32(o);
else
return 0;
}
}
//same for double.. etc
Run Code Online (Sandbox Code Playgroud)
我编写了这些方法,因为我必须处理很多数据库数据(来自OleDbDataReader),这些数据可以为null(不应该),因为底层数据库很可能非常宽松,列可能为null.为了让我的生活更轻松,我想出了那些扩展方法.
我想知道的是这是好风格,可接受的风格还是坏风格.我有点担心它,因为它有点"污染"对象类.
提前谢谢你和最好的问候:)
基督教
PS我没有故意将其标记为"主观".
我一直在设计一个数据库访问层,允许我们在程序中支持多个数据库.最后,我们程序的用户应该能够从一系列数据库系统中选择底层数据库系统.一些小客户可能对MS Access感到满意,其他人更喜欢MySql,其他人更喜欢DB2.那些db系统是我现在想要的目标.
鉴于这些要求,我想出了一个抽象类DatabaseConnection.在内部,我使用System.Data.Common.Data.DbConnection类,这已经给了我很大的灵活性.
需要具体实例的东西(例如OleDbCommand而不是DbCommand)隐藏在CreateDbCommand()等抽象方法中.子类(如AccessDbConnection)实现这些并提供具体实例.目前,这导致了这种层次结构(类名缩写为可读性):
Run Code Online (Sandbox Code Playgroud)DatabaseConnection / | \ AccessConn MySqlConn DB2Conn
但是,有一些特定于底层数据库系统的操作,例如检索所有表名.将抽象方法GetTableNames()放入DatabaseConnection类并让子类覆盖它是错误的.
我想也许我可以创建另一个名为DatabaseTools的抽象基类,在那里声明那些操作,然后在类似于DatabaseConnection类的子类的子类中实现它们.这意味着对于AccessDbConnection,我还有一个类AccessTools等等:
Run Code Online (Sandbox Code Playgroud)DatabaseConnection DatabaseTools / | \ / | \ AccessConn MySqlConn DB2Conn AccessTools MySqlTools DB2Tools
不知何故,我对这个想法并不感到激动.
您有什么想法来解决这个设计问题?
在此先感谢您的时间和答案:)
干杯
基督教
我在COM Interop遇到了一些麻烦,情况如下:
32位COM Exe服务器(用C++编程)提供了一个类,其中包含一些处理第三方硬件的成员函数(此硬件还将COM Exe Server绑定到32位,因为制造商不支持64-位).
我想在64位.NET(C#)应用程序中使用32位COM Exe Server ...首先,我尝试在Visual Studio 2010中添加对Exe Server的引用,并创建了一个Interop-DLL.这个Interop-DLL为我提供了必要的功能,其中一个被声明为:
int Initialize(ref string callingApplicationPath);
Run Code Online (Sandbox Code Playgroud)
C++中的原始声明如下所示:
LONG Class::Initialize(BSTR* callingApplicationPath)
Run Code Online (Sandbox Code Playgroud)
......在IDL中这样:
[id(1)] LONG Initialize([in] BSTR* callingApplicationPath);
Run Code Online (Sandbox Code Playgroud)
但是,当我想通过Interop-DLL从C#调用此函数时,它会抛出BadImageFormatException.看起来Interop-DLL是一个32位DLL(也许有可能生成64位DLL?).
我的下一次尝试是使用以下代码实例化Exe Server:
Type type = Type.GetTypeFromProgID("OurCompany.Class");
Object o = Activator.CreateInstance(type);
Object[] args = { Marshal.StringToBSTR(str) };
Object result = type.InvokeMember("Initialize", BindingFlags.InvokeMethod, null, o, args);
Run Code Online (Sandbox Code Playgroud)
另一方面,这段代码会抛出一个TargetInvocationException(更具体地说:0x80020005(DISP_E_TYPEMISMATCH)).不幸的是我无法找到我必须从C#传递给函数的类型...我在Marshal类中尝试了所有的StringToXXX函数但似乎没有任何工作:/我想我在这里缺少一些简单的东西,但我看不出来.
任何帮助是极大的赞赏!
最好的祝福
基督教
.net ×3
c# ×2
32bit-64bit ×1
c#-4.0 ×1
coding-style ×1
com ×1
data-access ×1
interop ×1
lambda ×1
oop ×1