程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 調用其他的動態庫開發應注意的問題,

C# 調用其他的動態庫開發應注意的問題,

編輯:C#入門知識

C# 調用其他的動態庫開發應注意的問題,


1.背景

程序開發語言可以說是五花八門,這就引出了一個新問題 ,不同語言開發的系統進行對接時相關調用的問題。

下面我主要說一下我自己在做接口開發時遇到的問題及解決方法僅供參考,我使用的C#開發進行對接其他程序。

2.具體做法

 首先,談一下目前系統對接的幾種常見對接方式。a.通過非托管的動態庫dll文件導入。b.通過對方提供的COM組件調用。c.通過webService進行調用。

目前比較常用的就這個幾種。下面一起看看都是如何具體調用實現以及遇到的問題。

a.通過非托管的動態庫dll文件導入

此種方式在C#中的通用聲明方式如下 。假如提供的dll 是InterfaceHN.dll   裡面提供的方法        long init( char *Addr, int Port, char *Servlet)

[DllImport("InterfaceHN.dll")]  這裡面還可以用  EntryPoint = "init",  CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true 屬性指定更詳細的信息 大家可以嘗試一下 ,一般情況下只要指定函數入口點就行例如[DllImport("InterfaceHN.dll", EntryPoint = "init")]

public static extern Int32 init( [MarshalAs(UnmanagedType.VBByRefStr)] ref string addr, Int32 port, [MarshalAs(UnmanagedType.VBByRefStr)] ref string servlet);

public static extern Int32 init( [ StringBuilder  addr, Int32 port,  StringBuilder servlet); 

在這種方式中,我以前遇到過的問題是內存保護,沒有改方法 ,調用方法返回的值不正確等等問題。

這塊就要注意參數的類型是不是兩種語言都支持的,或者說是兩種語言共有的 ,上面我就遇到過 ,文檔上描述的是返回long  值 ,但是實際上返回的是Int32  導致這邊出現內存保護提示。還有一點就是對於,帶有參數返回值的這種情況 ,在C#一般字符串使用 StringBuilder  就可以 ,不行的話試一試[MarshalAs(UnmanagedType.VBByRefStr)] ref string  paras  這種方式。出問題之後,首先自己檢查參數類型對不對,一般對方是不會有問題的,但也不排除對方給的dll本身就有問題。

b.通過對方提供的COM組件調用。

這種方式比較簡單,因為他本身就是一種接口標准。使用時只要注冊它,然後添加引用把它引入你的程序。實例化相關的對象就可以使用了。

具體注冊方法 :在系統運行窗口中輸入regsvr32 +com組件的地址 例如regsvr32 D:公共程序集\RM.ReportEngine.dll   取消注冊是在後面添加/u 開關。

c.通過webService進行調用。

此種調用也是目前比較方便流行的一種。只要給出服務的地址就可以進行 。但是有些環境你沒法訪問。例如vpn ,專網等等。這時就不能直接通過添加服務的方式進行訪問了,但是可以通過得到他們的服務描述xml文件進行訪問,如果還不行,就自己通過反射的方式建立客戶端代理具體如下:

public class WebServiceHelper
{
#region InvokeWebService 動態調用web服務

/// <summary>
/// 動態調用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="methodname">方法名(模塊名)</param>
/// <param name="args">參數列表</param>
/// <returns>object</returns>
public static object InvokeWebService(string url, string methodname, object[] args)
{
return WebServiceHelper.InvokeWebService(url, null, methodname, args);
}
/// <summary>
/// 動態調用WebService
/// </summary>
/// <param name="url">WebService地址</param>
/// <param name="classname">類名</param>
/// <param name="methodname">方法名(模塊名)</param>
/// <param name="args">參數列表</param>
/// <returns>object</returns>
public static object InvokeWebService(string url, string classname, string methodname, object[] args)
{
try
{

string @namespace = "EnterpriseServerBase.WebService.DynamicWebCalling";
if ((classname == null) || (classname == ""))
{
classname = WebServiceHelper.GetWsClassName(url);
}

//獲取WSDL
WebClient wc = new WebClient();
Stream stream = wc.OpenRead(url + "?WSDL");
ServiceDescription sd = ServiceDescription.Read(stream);
ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();
sdi.AddServiceDescription(sd, "", "");
CodeNamespace cn = new CodeNamespace(@namespace);

//生成客戶端代理類代碼
CodeCompileUnit ccu = new CodeCompileUnit();
ccu.Namespaces.Add(cn);
sdi.Import(cn, ccu);
CSharpCodeProvider csc = new CSharpCodeProvider();
ICodeCompiler icc = csc.CreateCompiler();

//設定編譯參數
CompilerParameters cplist = new CompilerParameters();
cplist.GenerateExecutable = false;
cplist.GenerateInMemory = true;
cplist.ReferencedAssemblies.Add("System.dll");
cplist.ReferencedAssemblies.Add("System.XML.dll");
cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
cplist.ReferencedAssemblies.Add("System.Data.dll");

//編譯代理類
CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);
if (true == cr.Errors.HasErrors)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (System.CodeDom.Compiler.CompilerError ce in cr.Errors)
{
sb.Append(ce.ToString());
sb.Append(System.Environment.NewLine);
}
throw new Exception(sb.ToString());
}

//生成代理實例,並調用方法
System.Reflection.Assembly assembly = cr.CompiledAssembly;
Type t = assembly.GetType(@namespace + "." + classname, true, true);
object obj = Activator.CreateInstance(t);
System.Reflection.MethodInfo mi = t.GetMethod(methodname);
if (args == null)
return mi.Invoke(obj, null);
else
return mi.Invoke(obj, args);
}
catch (Exception ex)
{
throw new Exception(ex.InnerException.Message, new Exception(ex.InnerException.StackTrace));
}
}

private static string GetWsClassName(string wsUrl)
{
string[] parts = wsUrl.Split('/');
string[] pps = parts[parts.Length - 1].Split('.');

return pps[0];
}
#endregion
}

通過類WebServiceHelper這的方法  InvokeWebService(string url, string methodname, object[] args) 完成對方webservice 的調用。

一般在調用其他系統的東西時經常出現內存問題,找不到方法問題,無法連接問題,返回值不是值期望的值問題。這些問題只要仔細認真的分析

就可以解決,沒有啥太難的東西。希望對你有幫助。


C語言中 ^怎使用

a1 = 0x01; //0000 0001
a2 = 0x00; //0000 0000
a3 = 0x03; //0000 0011
a4 = 0x02; //0000 0010

b1 = a1 ^ a2; //0000 0001
b2 = a1 ^ a3; //0000 0010
b3 = a1 ^ a4; //0000 0011

^異或運算符,位值相同為0,不同為1,見上示例.

//
簡單實際問題舉例:
======\=======\=======
======a=======b=======
上面是2條電路,2個開關分別為a和b,打開狀態:\[1],關閉狀態:/[0].
若同時打開或者關閉,兩條電路均不通.
若a打開[1],b關閉[0],電路1通電
======\=======/=======
若a關閉[0],b打開[1],電路2通電
======/=======\=======
綜上,電路在a,b狀態相同時不通[0],在a,b不同時通電[1].
 

C語言中 ^怎使用

a1 = 0x01; //0000 0001
a2 = 0x00; //0000 0000
a3 = 0x03; //0000 0011
a4 = 0x02; //0000 0010

b1 = a1 ^ a2; //0000 0001
b2 = a1 ^ a3; //0000 0010
b3 = a1 ^ a4; //0000 0011

^異或運算符,位值相同為0,不同為1,見上示例.

//
簡單實際問題舉例:
======\=======\=======
======a=======b=======
上面是2條電路,2個開關分別為a和b,打開狀態:\[1],關閉狀態:/[0].
若同時打開或者關閉,兩條電路均不通.
若a打開[1],b關閉[0],電路1通電
======\=======/=======
若a關閉[0],b打開[1],電路2通電
======/=======\=======
綜上,電路在a,b狀態相同時不通[0],在a,b不同時通電[1].
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved