解惑

解己之惑,解人之惑

分类:.net (第1页共4页)

反射获取集合中指定下标的元素

不废话了,直接上代码吧:

public static object GetElementFromCollection(object obj, int index)
{
Type type = obj.GetType();
if (type.IsArray)
{
return ((Array) obj).GetValue(index);
}
else
{
object[] attributes = type.GetCustomAttributes(typeof(DefaultMemberAttribute), true);
DefaultMemberAttribute attribute = (DefaultMemberAttribute) attributes[0];
String indexerName = attribute.MemberName;
type.GetProperties();
PropertyInfo pi2 = type.GetProperty(indexerName, new Type[] { typeof(int) });
return pi2.GetValue(obj, new Object[] {index});
}
}

用C#动态调用WebService

其实利用的都是前人的成果:C# – Dynamically Invoke Web Service At Runtime

这个文章的问题是没有提及需要认证的时候怎么办,但是后面很多回帖都问到了,总结下:

在读取WSDL的时候有几种方式,我使用的是:

WebClient client = new WebClient();

if (_needCredential)
{
client.Credentials = _credential;
}
Stream stream = client.OpenRead(WSDL);
XmlTextReader xmlreader = new XmlTextReader(stream);

//XmlTextReader xmlreader = new XmlTextReader(Uri);
ServiceDescriptionImporter descriptionImporter = BuildServiceDescriptionImporter(xmlreader);
Assembly library = CompileAssembly(descriptionImporter);

在真正生成WebService的Instance以后,需要设置Instance的几个Property:

if (_needCredential)
{
PropertyInfo preAuthenticate = GetRealType().GetProperty(“PreAuthenticate”);
preAuthenticate.SetValue(Result, true, null);
PropertyInfo url = GetRealType().GetProperty(“Url”);
url.SetValue(Result, Url, null);
CredentialCache cache = new CredentialCache();
Uri uri = new Uri(Url);
cache.Add(uri, “Basic”, _credential);
PropertyInfo credentials = GetRealType().GetProperty(“Credentials”);
credentials.SetValue(Result, cache, null);
}

测试框架

最近在做C#版的测试框架,目的其实是让QA不用写代码就可以测试API,QA需要写一些XML,然后交给这个测试框架运行。

设计其实比较直接,把功能测试中的一些概念抽取出来包装下就可以了,XML要人可读可写,然后能够直接转换为对应的类,免去解析的过程最好。

我提取出来的主要概念如下:

  • Library,对应的其实就是DLL,就像java中的jar一样,可以从指定的路径load,也可以从系统的GAC(windows特定的东西)里面load。
  • Instance,其实本来想叫Object,因为是关键字,只能取这个比较紧似的名字,另外,声明的也确实是对象的instance而不是对象定义。
    • List,集合类型,可以当成List或者Array用。
    • WebService,这个是Instance的子类可能有点怪,但是框架的工作机制是生成WebService的Stub的对应的类,所以其实也是Instance,只是有一些额外的属性。
  • Operation,其实就是操作了,有很多子类型:
    • Method,就是方法调用了
    • Verify,主要是为了做结果验证,其实也是Method,只不过掩盖了实现,我用的就是NUit的实现。
    • Task,Operation的集合,本来想加一个Function的,但是感觉Function和Task功能完全一样。Task就相当于功能测试或者单元测试的一个方法。
    • Express,表达式,主要是为了支持简单的字符串连接和数学运算。
    • Field,获取或者设置Instance的field,我掩盖了C#中的Property和Field的区别,只提供Field,两种都可以访问。
    • Loop,其实也是Operation的集合,但是会把集合中的Operation重复执行很多次,用于性能测试或者批量调用,会生成一个索引值供Operation引用生成不同的值。
    • Indexer,访问集合类型中的某个指定下标的元素,主要是因为C#没有像Java一样提供Get(int index)方法,否则这个完全没有,直接用Method 就可以实现了。
    • Finder,主要是简化了从集合类型中查找某个元素,框架没有提供if/else这样的逻辑控制,只能提供这个变向的方式。
    • Wait,主要是提供Sleep以及异步调用支持,是Verify的子类型,可以每隔一段时间Verify一下,看看结果是不是match,然后有超时,超时就认为Veirfy失败。
  • Define,就是组件声明,里面包含的就是上面提到的那些东西。
  • Suite,就是Test Case了,包含Define列表和Task列表,以及Startup/Teardown

基本上已经涵盖测试中需要的大部分内容了。

一些额外的想法,Operation还是有很大扩展余地的,例如可以支持外部调用,例如调用一个命令行或者其它的程序。

反射创建一个指定类型的List

由于最近在做C#版的测试框架,所以对C#的反射研究得比较多一点,这里是另外一个心得,由于运行时才知道类型,所以如何创建一个指定类型的List?其实很简单:

Type elementType = realType;
Type listType = typeof(List<>);
Type typedListType = listType.MakeGenericType(elementType);

使用批处理删除一个月以前的文件

这个其实是上一篇文件备份的延续,既然备份了,备份越来越大当然不行,一般保留一个月的备份就足够了,DOS的功能也基本上能够满足这个要求,不废话,直接给脚本了:

rem Backup
y:
cd y:\01_projects\08_saas\TargetProcessDB
set dirname=%date:~10,4%-%date:~4,2%-%date:~7,2%
mkdir %dirname%
cd %dirname%
copy F:\DailyBackup\*.* .
cd ..

rem Remove backup  of one month ago based on dir name
set year=%date:~10,4%
set month=%date:~4,2%
set day=%date:~7,2%
set monthprefix=%month:~0,1%
if %month%==01 goto _lastYear
if %monthprefix% EQU 0 goto _onebitmonth
goto _twobitsmonth

:_lastYear
set /a year=%year%-1
set deldate=%year%-12-%day%
goto _execute

:_onebitmonth
set /a oldmonth=%month:~1,1%-1
set deldate=%year%-0%oldmonth%-%day%
goto _execute

:_twobitsmonth
set /a oldmonth=%month%-1
if %oldmonth% EQU 9 (
set deldate=%year%-0%oldmonth%-%day%
)
else (
set deldate=%year%-%oldmonth%-%day%
)
goto _execute

:_execute
for /f %%d in (‘dir /b /d’) do if %%d LSS %deldate% rmdir /s /q %%d

应该看得懂吧。最后一行要留意下,定义变量的时候用了两个%号,这个是必须的。另外就是日期问题,不用关注闰年问题,因为是进行的字符串比较,日期(例如2010-02-29)即使不是合法日期也是没有关系的。另外就是日期的格式,因为是上一篇的延续,所以当然针对的是上一篇的日期格式了。

更新:

又搜索 了下,如果根据目录自己的创建时间来操作,有更简单的方法:

forfiles /p . /m * /d -30 /c “cmd /c rmdir /s /q @path”

如果是遍历所有的子目录删除文件,也很简单:

forfiles /p . /m *.* /d -30 /c “cmd /c del @path”

c#反射之Enum篇

因为最开始就遇到这个问题,所以单独提出来,不废话了,上代码吧

Assembly assembly = Assembly..Load(“MyDLL”);
Type type = assembly.GetType(“MyDLL.MyEnum”);
FieldInfo enumItem = type.GetField(“ENUM_TEST”);
object enumValue= Enum.ToObject(type, enumItem.GetValue(type));
最后一行代码得到的就是对应的enum对象的实例,可以传递给方法调用,type.GetField方法中的字符串其实就是enum中的字符串名字。要得到这个名字的列表也很容易:

string[] names = Enum.GetNames(type);

c#反射入门篇

主要就是几点

加载DLL

通过Assembly类的方法,主要是Load,还有其他一些方法可以自己研究下,Load方法可以传一个简单名,也可以传完整的限定名,传简单名(MyDLL)的时候,对应的DLL文件(MyDLL.dll)必须位于当前目录?(或者是PATH里面),如果是引用系统注册的DLL,则必须是完整的限定名,例如:MyDLL, Version=1.0.0.0, Culture=Neutral, PublickeyToken=d3cc2ceeafb73bc1

得到Type

这个没有什么,调用上面得到Assembly实例的GetType就行了

创建实例

得到Type以后,使用Activator.CreateInstance就可以了

调用方法

通过Type的GetMethod得到需要调用的MethodInfo对象,然后调用MethodInfo的Invoke方法。

废话少说,看代码吧:

Assembly assembly = Assembly..Load(“MyDLL”);
Type type = assembly.GetType(“MyDLL.MyClass”);
object obj = Activator.CreateInstance(type);
MethodInfo createMethod = type.GetMethod(“MyMethod”);
object[] parameters = new object[1];
parameters[0] = “ParameterValue”
object result = createMethod.Invoke(obj, parameters);

其实和Java差不多,就是java不需要load那一步,因为默认是从CLASSPATH中的所有jar中都可以load的,这个是JVM做的事情。如果需要load其他的不在CLASSPATH中的jar也是可以的,比较麻烦而已。

研究c#的反射机制

要做一个通用的自动测试框架,通过写xml文件完成Test Case的构建,由于打算支持COM和普通的DLL的方法调用,所以必须基于反射来做了。

大概看了下,好像也不是很复杂,就是得一步一步的试了。

Regsvr32: 0x80070716

注册Dll的时候遇到这个错误,当然,我是在开发一个新的自己的DLL,或者是我修改已有的DLL增加我自己的东西,已经遇到好几次这个错误了。这个错误的对应的错误信息是:

the resource name specified cannot be found in the image file

其实我已经遇到过几次了,上次解决过一次,但是忘记了,这次吸取教训,把它记下来。

我的错误是因为我增加了一些类,idl修改好了,rgs文件也都写好了,但是我忘记了在rc文件里面把那些rgs文件引用下。

_nt_symbol_path

备忘下,设置这个环境变量后可以调试系统的DLL,可以自动从微软的网站下载PDB:

Set _NT_SYMBOL_PATH = symsrv*symsrv.dll*f:\localsymbols*http://msdl.microsoft.com/download/symbols

不过加上以后调试超级慢,平时还是不要用了。

更早的文章

© 2021 解惑

本主题由Anders Noren提供向上 ↑