English 中文(简体)
How do WPF Markup Extensions raise compile errors?
原标题:
  • 时间:2009-11-09 15:49:01
  •  标签:
  • c#
  • wpf

Certain markup extensions raise compile errors. For example StaticExtension (x:Static) raises a compile error if the referenced class cannot be found. Anyone know the mechanism for this? Is it baked into the XAML compiler or is such functionaility available to custom markup extensions?

EDIT: mfeingold below suggested that I need to look into the IVsErrorList interface, but I can t immediately see how that would help someone white a markup extension that generates a compile-time error. Any examples?

最佳回答

Extending the BAML compile process to log additional errors

I encountered this same problem last year. I was writing my own extension for which I wanted compile-time errors in certain scenrios and discovered that just throwing an exception from ProvideValue didn t work because ProvideValue isn t called until the XAML is actually loaded and the object tree is created.

I did some experiments and discovered that the compiler error message for x:Static is a byproduct of an optimization done by the the BAML compiler. The BAML format actually has a concept of a specific member of a specific type, so when the XAML contains x:Static the compiler actually replaces it with a special record that directly references the member rather than containing the type and method name. It does this by explictly recognizing the StaticExtension class. TypeExtension has a similar optimization.

I searched for hooks that would allow me to have my own code called during BAML compilation, but I didn t find any. BAML compilation is mostly just a straight transliteration into a binary format that corresponds to the XAML, with a few specific optimizations but mostly ignoring what it sees.

I ended up adding an extra step to the build process, modeling my code off of Microsoft.WinFX.targets and the other built-in targets files. This step scans the XAML for my markup extension, checks the parameters, and generates a compile error if they are not correct. This is done completely independently of the translation into BAML. It was a couple days extra work to implement this when all was said and done, but I learned a lot.

Caveat about creating your own .targets file

If you re thinking about adding your own .targets file, you should be aware that unless you include the target in the local machine s SafeImports registry key, both Visual Studio and Expression Blend will complain that about any project that includes your .targets file. This key requires Administrator access on the machine to update. This may or may not be an issue depending on your deployment scenario. (For example, a machine-wide MSI install would fix it, or you could manually set the key if you only have a few development machines). In my case it didn t matter since I already needed the custom .targets file for some other things I was doing in that project.

Error logging from a build task

You don t need IVsErrorList to add errors to Visual Studio during a build (and if you did, you would not properly support command-line builds, Expression Blend, and other tools).

All you need to do is to call Log.LogErrror Log.LogWarning from inside your build task, like this:

public class CheckForErrorsInMyMarkupExtension : Task
{
  ... parameters here ...

  public override Execute()
  {
    ... code to load XAML and scan it for markup extension errors ...
    ... when you discover an error ...
      Log.LogError("I saw an error");
  }
}
问题回答

There are several VisualStudio integration API which allows you to generate your own diagnostic messages from a MEF extension (VS2010 only) a VSIntegration Package or an add-in.

check out IVsErrorList interface as well as OutputTaskItemString method of the IVsOutputWindowPane interface. The latter is what I used in my django editor.

The calls to these methods of course are baked into XAML compiler - how could they not be, they are based on results of the XAML parsing





相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签