C# .NET은 IdisPatch 후기 바인딩을 지원합니까?
-
03-07-2019 - |
문제
질문
내 질문은 다음과 같습니다. C#은 후반에 늦은 바인딩 IDISPATCH를 지원합니까?
인 척하다 고객이 설치 한 버전과 호환되는 동안 사무실을 자동화하려고합니다.
.NET World에서 Office 2000 설치로 개발 한 경우, 모든 개발자 및 모든 고객은 지금부터 시간이 끝날 때까지 Office 2000을 가져야합니다.
.NET 이전의 세계에서 우리는 사용했습니다 com 사무실 신청서와 대화합니다.
예를 들어:
1) 버전 Independent Progid를 사용하십시오
"Excel.Application"
다음으로 해결됩니다.
clsid = {00024500-0000-0000-C000-000000000046}
그런 다음 COM을 사용 하여이 클래스 중 하나가 개체로 인스턴스화하도록 요청합니다.
IUnknown unk;
CoCreateInstance(
clsid,
null,
CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
IUnknown,
out unk);
그리고 이제 우리는 경주에서 벗어났습니다 - 내 응용 프로그램 내부에서 Excel을 사용할 수 있습니다. 당연하지 만약 진짜 객체를 사용하려면 전화 방법이 있어야합니다.
우리 ~할 수 있었다 다양한 것을 얻으십시오 상호 작용 우리의 언어로 번역 된 선언. 이 기술은 우리가 얻기 때문에 좋습니다
- 초기 바인딩
- 코드 안내
- 유형 구문 검사를 컴파일합니다
코드는 다음과 같습니다.
Application xl = (IExcelApplication)unk;
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
Worksheet worksheet = workbook.ActiveSheet;
그러나 인터페이스 사용의 단점이 있습니다. 우리는 다양한 인터페이스 선언을 받아야하며 언어로 전환해야합니다. 그리고 우리는 메소드 기반 호출을 사용하여 모든 매개 변수를 지정해야합니다.
ExcelWorkbook workbook = xl.Workbooks.Add(template, lcid);
xl.Worksheets.Add(before, after, count, type, lcid);
이것은 실제 세계에서 우리가 기꺼이 포기할 그러한 단점을 가지고 있음을 증명했습니다.
- 초기 바인딩
- 코드 안내
- 시간 구문 확인을 컴파일합니다
대신 사용합니다 Idispatch 늦은 바인딩 :
Variant xl = (IDispatch)unk;
Variant newWorksheet = xl.Worksheets.Add();
Excel Automation은 VB 스크립트 용으로 설계되었으므로 오버로드가없는 경우에도 많은 매개 변수를 획득 할 수 있습니다.
메모: idispatch를 사용하고 싶은 이유와 Excel의 예제를 혼동하지 마십시오. 모든 com 객체가 탁월한 것은 아닙니다. 일부 COM 객체는 idispatch를 통한 것 외에는 지원이 없습니다.
해결책
상대적으로 C#에서 늦은 바인딩 Idispatch 바인딩을 사용할 수 있습니다.
http://support.microsoft.com/kb/302902
Excel을 사용하기위한 샘플이 있습니다. 이렇게하면 Microsoft의 Bloaty PIA에 불필요한 종속성을 추가 할 필요가 없습니다.
//Create XL
Object xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
//Get the workbooks collection.
// books = xl.Workbooks;
Object books = xl.GetType().InvokeMember( "Workbooks",
BindingFlags.GetProperty, null, xl, null);
//Add a new workbook.
// book = books.Add();
Objet book = books.GetType().InvokeMember( "Add",
BindingFlags.InvokeMethod, null, books, null );
//Get the worksheets collection.
// sheets = book.Worksheets;
Object sheets = book.GetType().InvokeMember( "Worksheets",
BindingFlags.GetProperty, null, book, null );
Object[] parameters;
//Get the first worksheet.
// sheet = sheets.Item[1]
parameters = new Object[1];
parameters[0] = 1;
Object sheet = sheets.GetType().InvokeMember( "Item",
BindingFlags.GetProperty, null, sheets, parameters );
//Get a range object that contains cell A1.
// range = sheet.Range["A1];
parameters = new Object[2];
parameters[0] = "A1";
parameters[1] = Missing.Value;
Object range = sheet.GetType().InvokeMember( "Range",
BindingFlags.GetProperty, null, sheet, parameters );
//Write "Hello, World!" in cell A1.
// range.Value = "Hello, World!";
parameters = new Object[1];
parameters[0] = "Hello, World!";
objRange_Late.GetType().InvokeMember( "Value", BindingFlags.SetProperty,
null, range, parameters );
//Return control of Excel to the user.
// xl.Visible = true;
// xl.UserControl = true;
parameters = new Object[1];
parameters[0] = true;
xl.GetType().InvokeMember( "Visible", BindingFlags.SetProperty,
null, xl, Parameters );
xl.GetType().InvokeMember( "UserControl", BindingFlags.SetProperty,
null, xl, Parameters );
다른 팁
당신은 당신이 찾고있는 늦은 바인딩을 얻기 위해 C# 4.0이 나올 때까지 기다려야합니다. 인터롭 기능이 필요할 때마다 VB.NET 모드로 다시 전환하여 C#이 부족한 것으로 보이는 COM 기능을 활용할 수 있습니다.
내가 사용하는 간단한 방법은 vb.net에서 idispatch 작업을 수행하는 클래스를 작성한 다음 래퍼의 메소드로 사용하려는 메소드를 노출 한 다음 C# 코드에서 마음대로 호출 할 수 있습니다. 가장 우아한 솔루션은 아니지만 지난 몇 개월 동안 잼에서 두 번 떨어졌습니다.
C# 4 dynamic
키워드는 Idispatch 및 늦은 바인딩을 지원합니다. Sam Ng 's를 읽을 수 있습니다 동적 시리즈 자세한 내용은
아, 그리고 C# 4는 오늘 CTP로만 제공됩니다. Visual Studio VNEXT를 기다리거나 베타 (Windows Server 2008 Virtual PC에서 실행되는 베타)를 사용하여 사용해야합니다.
아마도 C# 2.0/3.0에서 훨씬 더 좋은 코드로 도망 갈 수있을 것입니다. 객체에 원하는 메소드와 속성이 포함 된 인터페이스를 작성하고 일부 속성을 추가하는 데 시간이 걸리면 메모리에서 글을 쓰지 않으므로 세부 사항이 아닙니다. 맞아, 나는 그것이 나를 위해 일했다고 맹세한다 ...)
using System.Runtime.Interopservices;
[Guid("00024500-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
interface IExcel
{
// sample property
string Name{get;}
// more properties
}
// and somewhere else
void main()
{
Object xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
IExcel excel = (IExcel)xl;
string name = xl.name
}
언급했듯이 코드는 상자에서 작동하지 않으며 MSDN에서 무엇을 파는지 더 힌트입니다.
다른 사람들이 말했듯이 C#4의 "동적"키워드 암석을 사용합니다. 간단한 예는 다음과 같습니다.
dynamic xl = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
dynamic books = xl.Workbooks;
dynamic book = books.Add();
Console.WriteLine(books.Count); //Writes 1
foreach (dynamic b in books)
{
Console.WriteLine(b.Name); //Writes "Book1"
}
이봐,이 문제를 해결하기 위해 현재 2 개의 코드 플렉스 프로젝트가 있습니다.
첫 번째는 LateBindingApi.excel입니다 http://excel.codeplex.com잘 알려진 객체 모델로 호출을 호출하는 맵핑. 이것은 다음 프로젝트의 테스트 프로젝트였습니다.
두 번째는 CodeGenerator입니다 http://latebindingapi.codeplex.com이 도구는 COM 유형 라이브러리에서 C# 프로젝트를 만듭니다. 생성 된 프로젝트에는 Latebind가 COM 서버에 액세스하는 맵퍼 객체가 포함됩니다. 하이라이트는 도구가 다른 버전의 Libs를 하나의 단일 프로젝트 (예 : Excel 9,10,11)로 변환하고 모든 엔티티를 자체 정의 된 supportBylibrary 속성으로 표시 한 것입니다. 이 도구를 사용하여 버전 9,10,11,12,14의 모든 사무실 앱을 분석하고 메인 페이지에서 샘플 코드로 테스트 된 베타로 사용할 수있는 AC# 솔루션을 생성했습니다.