开发者

Passing a namespace into a function

I've got a function which takes a word document and saves it in html format. I'd like to use the same function to work with any document type. I'开发者_StackOverflow社区ve tried using generics (I'm assumming the different doc APIs are the same) which fails due to the reason Jon Skeet pointed out. Is there another way?

using Word = Microsoft.Office.Interop.Word;
using Excel = Microsoft.Office.Interop.Excel;

//Works ok
private void convertDocToHtm( string filename )
{
... snip

     var app = new Word.Application();
     var doc = new Word.Document();
     doc = app.Documents.Open(ref fileName, ref missing, ref trueValue, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);

... snip    
}

//fails dismally (to compile) because 'T' is a 'type parameter', which is not valid in the given context - i.e Word is a namespace not a class
private void convertDocToHtm2<T>( string filename )
{
... snip

     var app = new T.Application();
     var doc = new T.Document();
     doc = app.Documents.Open(ref fileName, ref missing, ref trueValue, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);

... snip
}

//calling examples
convertDocToHtm( filename );
convertDocToHtm2<Word>( filename );
convertDocToHtm2<Excel>( filename );


No, this isn't possible. Type parameters are for types, not namespaces.

In particular, the compiler couldn't verify that such a type even existed - you could call ConvertDocToHtm2<System> for example.

With dynamic typing in C# 4, you could do something this:

private void ConvertDocToHtm2<TApplication>(string filename)
    where TApplication : new()
{
     dynamic app = new TApplication();
     dynamic doc = app.Documents.Open(filename, html: trueValue);
     // Other stuff here
}

Then:

ConvertDocToHtm2<Word.Application>(filename);

(I've guessed at the parameter name for trueValue by the way - you'd want to verify that.)


Once you have the objects, dynamic may be a good fit here (for calling methods and accessing properties etc) - however, that only applies to variables, not namespaces.

If you really need the namespace (I don't think you do), you could pass it in as a string and use Activator.CreateInstance(namespace + ".Application").

However, reading it - it seems that only the application is needed; perhaps:

private void convertDocToHtm2<T>( string filename ) where T : class, new();
{
     dynamic app = new T();
     dynamic doc = app.Documents.Open(fileName);

     // etc
}

and call as convertDocToHtm2<Word.Application>(filename)


That's not possible, because generics in C# are a compile time feature and the type must be known at compile time. That's not possible, because the APIs of the different Office Applications don't share a common base class. In C++ it could work, because the C++ templates are compiled into classes that are evaluated at runtime. But even then it would only work for small parts of the API, because they are not the same!


If you don't want to use dynamic types, and if you only use a few methods in each namespace, and if those methods have the same signature, you can construct your ConvertDocToHtml2 to accept delegates. Then pass the methods under Word/Excel as those delegates.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜