I am currently trying to use the AST functionality introduced in PowerShell 3.0 to modify a ScriptBlock. My requirement is that all the parameters in the parameter block of the ScriptBlock get a [Parameter(Mandatory)] attribute.
Basically the code should modify this:
Param([string]$x)
Write-Host $x
to this:
Param([Parameter(Mandatory)][string]$x)
Write-Host $x
However, I ran into a problem when adding that new attribute, since it expects an IScriptExtent and I am not sure how I should create a new IScriptExtent.
How can I create a new script extent? What values can I use for the position? Do I have to change the position of all following extents?
I tried just reusing the extent of each parameter I am modifying, but unfortunately this does not seem to yield the results it should (e.g. when I am calling ToString on the modified ScriptBlock I don't see any changes).
My implementation so far is based on the ICustomAstVisitor found here.
The most important method looks like this:
public object VisitParameter(ParameterAst parameterAst)
{
var newName = VisitElement(parameterAst.Name);
var extent = // What to do here?
var mandatoryArg = new AttributeAst(extent, new ReflectionTypeName(typeof (ParameterAttribute)),
new ExpressionAst[0],
new[] {new NamedAttributeArgumentAst(extent, "Mandatory", new ConstantExpressionAst(extent, true), true)});
var newAttributes = new[] {mandatoryArg}.Concat(VisitElements(parameterAst.Attributes));
var newDefaultValue = VisitElement(parameterAst.DefaultValue);
return new ParameterAst(parameterAst.Extent, newName, newAttributes, newDefaultValue);
}
The script extent is used primarily for error reporting, but is also used for debugging (for example, setting a line breakpoint.)
In general, the options for synthesized script (like your example) are:
reuse an existing ast, presumably near/related to the ast you're adding
use an empty ast (basically create instances of ScriptExtent and ScriptPosition with no file, empty line)
create a synthetic extent that aids in debugging somehow, maybe with some special content
In your example, any of the above are suitable. The second option is the simplest. The third option is just a variant of the second, but you would set the content to something useful, e.g.
<#Generated: [Parameter(Mandatory)] #>
Names that begin with I are typically Interfaces. They are not classes that you create an instance of, they are contracts of sorts that specify that a particular class implements a certain known set of functionality.
For example, a [hashtable] implements IEnumerable. That means that anything that knows how to work with an IEnumerable interface and operate on that class; you could create your own class that implements the interface, and code that never could have known about your class or what it does can still interact with it in the way that IEnumerable defines (which in this case is a way to iterate over it).
So, when a function declares a parameter with an interface type, it's not looking for any one specific class, it's looking for any class that implements that interface.
The next step then is to find which types implement that interface. Here's some PowerShell code I used to find those:
[System.AppDomain]::CurrentDomain.GetAssemblies().GetTypes() | Where-Object {
[System.Management.Automation.Language.IScriptExtent].IsAssignableFrom($_)
}
From this, we can see the following:
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False IScriptExtent
False False InternalScriptExtent System.Object
False False EmptyScriptExtent System.Object
True False ScriptExtent System.Object
The first listing is the interface itself. Of the other three, two of them are not public, so that just leaves ScriptExtent.
You can create one of these with New-Object but you need to supply the start and end positions as [ScriptPosition] objects. I'm not entirely sure what those should be without seeing more of your code.
Related
I have read in various places that Global variables are at best a code smell, and best avoided. At the moment I am working on refactoring a big function based PS script to classes, and thought to use a Singleton. The use case being a large data structure that will need to be referenced from a lot of different classes and modules.
Then I found this, which seems to suggest that Singletons are a bad idea too.
So, what IS the right way (in PS 5.1) to create a single data structure that needs to be referenced by a lot of classes, and modified by some of them? Likely pertinent is the fact that I do NOT need this to be thread safe. By definition the queue will be processed in a very linear fashion.
FWIW, I got to the referenced link looking for information on singletons and inheritance, since my singleton is simply one of a number of classes with very similar behavior, where I start with the singleton which contains collections of the next class, which each contain collections of the next class, to create a hierarchical queue. I wanted to have a base class that handled all the common queue management then extend that for the differing functionality lof each class. Which works great other than having that first extended class be a singleton. That seems to be impossible, correct?
EDIT: Alternatively, is it possible with this nested classes in a generic list property approach to be able to identify the parent from within a child? This is how I handled this is the Function based version. A global [XML] variable formed the data structure, and I could step through that structure, using .SelectNode() to populate a variable to pass to the next function down, and using .Parent to get information from higher up, and especially from the root of the data structure.
EDIT: Since I seem not to be able to paste code here right now, I have some code on GitHub. The example here of where the Singleton comes in is at line 121, where I need to verify if there are any other examples of the same task that have not yet comnepelted, so I can skip all but the last instance. This is a proof of concept for deleting common components of various Autodesk software, which is managed in a very ad hoc manner. So I want to be able to install any mix of programs (packages) and uninstall on any schedule, and ensure that the last package that has a shared component uninstall is the one that uninstalls it. So as to no break other dependent programs before that last uninstall happens. Hopefully that makes sense. Autodesk installs are a fustercluck of misery. If you don't have to deal with them, consider yourself lucky. :)
To complement Mathias R. Jessen's helpful answer - which may well be the best solution to your problem - with an answer to your original question:
So, what IS the right way (in PS 5.1) to create a single data structure that needs to be referenced by a lot of classes, and modified by some of them [without concern for thread safety]?
The main reason that global variables are to be avoided is that they are session-global, meaning that code that executes after your own sees those variables too, which can have side effects.
You cannot implement a true singleton in PowerShell, because PowerShell classes do not support access modifiers; notably, you cannot make a constructor private (non-public), you can only "hide" it with the hidden keyword, which merely makes it less discoverable while still being accessible.
You can approximate a singleton with the following technique, which itself emulates a static class (which PowerShell also doesn't support, because the static keyword is only supported on class members, not the class as a whole).
A simple example:
# NOT thread-safe
class AlmostAStaticClass {
hidden AlmostAStaticClass() { Throw "Instantiation not supported; use only static members." }
static [string] $Message # static property
static [string] DoSomething() { return ([AlmostAStaticClass]::Message + '!') }
}
[AlmostAStaticClass]::<member> (e.g., [AlmostAStaticClass]::Message = 'hi') can now be used in the scope in which AlmostAStaticClass was defined and all descendant scopes (but it is not available globally, unless the defining scope happens to be the global one).
If you need access to the class across module boundaries, you can pass it as a parameter (as a type literal); note that you still need :: to access the (invariably static) members; e.g.,
& { param($staticClass) $staticClass::DoSomething() } ([AlmostAStaticClass])
Implementing a thread-safe quasi-singleton - perhaps for use
with ForEach-Object -Parallel (v7+) or Start-ThreadJob (v6+, but installable on v5.1) - requires more work:
Note:
Methods are then required to get and set what are conceptually properties, because PowerShell doesn't support code-backed property getters and setters as of 7.0 (adding this ability is the subject of this GitHub feature request).
You still need an underlying property however, because PowerShell doesn't support fields; again the best you can do is to hide this property, but it is technically still accessible.
The following example uses System.Threading.Monitor (which C#'s lock statement is based on) to manage thread-safe access to a value; for managing concurrent adding and removing items from collections, use the thread-safe collection types from the System.Collections.Concurrent namespace.
# Thread-safe
class AlmostAStaticClass {
static hidden [string] $_message = '' # conceptually, a *field*
static hidden [object] $_syncObj = [object]::new() # sync object for [Threading.Monitor]
hidden AlmostAStaticClass() { Throw "Instantiation not supported; use only static members." }
static SetMessage([string] $text) {
Write-Verbose -vb $text
# Guard against concurrent access by multiple threads.
[Threading.Monitor]::Enter([AlmostAStaticClass]::_syncObj)
[AlmostAStaticClass]::_message = $text
[Threading.Monitor]::Exit([AlmostAStaticClass]::_syncObj)
}
static [string] GetMessage() {
# Guard against concurrent access by multiple threads.
# NOTE: This only works with [string] values and instances of *value types*
# or returning an *element from a collection* that is
# only subject to concurrency in terms of *adding and removing*
# elements.
# For all other (reference) types - entire (non-concurrent)
# collections or individual objects whose properties are
# themselves subject to concurrent access, the *calling* code
# must perform the locking.
[Threading.Monitor]::Enter([AlmostAStaticClass]::_syncObj)
$msg = [AlmostAStaticClass]::_message
[Threading.Monitor]::Exit([AlmostAStaticClass]::_syncObj)
return $msg
}
static [string] DoSomething() { return ([AlmostAStaticClass]::GetMessage() + '!') }
}
Note that, similar to crossing module boundaries, using threads too requires passing the class as a type object to other threads, which, however is more conveniently done with the $using: scope specifier; a simple (contrived) example:
# !! BROKEN AS OF v7.0
$class = [AlmostAStaticClass]
1..10 | ForEach-Object -Parallel { ($using:class)::SetMessage($_) }
Note: This cross-thread use is actually broken as of v7.0, due to classes currently being tied to the defining runspace - see this GitHub issue. It is to be seen if a solution will be provided.
As you can see, the limitations of PowerShell classes make implementing such scenarios cumbersome; using Add-Type with ad hoc-compiled C# code is worth considering as an alternative.
This GitHub meta issue is a compilation of various issues relating to PowerShell classes; while they may eventually get resolved, it is unlikely that PowerShell's classes will ever reach feature parity with C#; after all, OOP is not the focus of PowerShell's scripting language (except with respect to using preexisting objects).
As mentioned in the comments, nothing in the code you linked to requires a singleton.
If you want to retain a parent-child relationship between your ProcessQueue and related Task instance, that can be solved structurally.
Simply require injection of a ProcessQueue instance in the Task constructor:
class ProcessQueue
{
hidden [System.Collections.Generic.List[object]]$Queue = [System.Collections.Generic.List[object]]::New()
}
class Task
{
[ProcessQueue]$Parent
[string]$Id
Task([string]$id, [ProcessQueue]$parent)
{
$this.Parent = $parent
$this.Id = $id
}
}
When instantiating the object hierarchy:
$myQueue = [ProcessQueue]::new()
$myQueue.Add([Task]#{ Id = "id"; Parent = $myQueue})
... or refactor ProcessQueue.Add() to take care of constructing the task:
class ProcessQueue
{
[Task] Add([string]$Id){
$newTask = [Task]::new($Id,$this)
$Queue.Add($newTask)
return $newTask
}
}
At which point you just use ProcessQueue.Add() as a proxy for the [Task] constructor:
$newTask = $myQueue.Add($id)
$newTask.DisplayName = "Display name goes here"
Next time you need to search related tasks from a single Task instance, you just do:
$relatedTasks = $task.Parent.Find($whatever)
I want to modify the ACL of a specific folder. To do this, I need to remove the inherited FileSystemAccessRules, and change them to ReadAndExecute permissions. To do this, I decided to use the ModifyAccessRule() method.
My problem is that I need to use the ModifyAccessRule method, and as part of the constructor, I need a FileSystemAccessRule object that would take the same input.
I am aware that this could be simply solved by not using a pipeline, but I am trying to keep it efficient and within one, hence why no external variables are being used (with the exception of the initial path).
Get-Item $folder_path |
%{$_.GetAccessControl()} |
%{$_.ModifyAccessRule(
"Add",
New-Object System.Security.AccessControl.FileSystemAccessRule(
$_.Access.IdentityReference,
[System.Security.AccessControl.FileSystemRights]::ReadAndExecute,
[System.Security.AccessControl.InheritanceFlags]::ContainerInherit,
[System.Security.AccessControl.PropagationFlags]::None,
[System.Security.AccessControl.AccessControlType]::Allow
)
)}
This is my code at the moment, but it does not work, due to New-Object not being executable inside a constructor. I have searched for a possible replacement, but have not found anything. As you can see, though, all the parts necessary for this new object are available.
Is there some type of format or method I could use to create this FileSystemAccessRule object within another object's constructor?
PS: As a bonus, can anyone confirm that PropagationFlags and InheritanceFlags are at the right values for the folder to not inherit parent permissions but propagate to children? ^-^
Assume I am populating an object's properties and I need to pass in one of the properties to another method, is it OK to reference a property from the new object or should I set a separate variable first and use it? Is one way better than the other? Keep in mind I have not called SaveChanges().
Method #1 (use property from new object)
=================================================
newObject.LegacyId = oldObject.Id;
newObject.NewId = GetNewIdFromLegacyId(newObject.LegacyId);
Method #2 (set separate variable)
=================================================
int legacyId = oldObject.Id;
newObject.LegacyId = legacyId;
newObject.NewId = GetNewIdFromLegacyId(legacyId);
I have to assume that both methods are equivalent.
The only thing that could make things different here is when there is more code in the getter or setter of newObject.LegacyId than just storing/returning a member variable, by which you'd return a different value than the set value. This would be highly insensible and unexpected. (And therefore unlikely you're actually doing this).
So it's really a matter of taste which method you prefer. I think personally I might prefer a third method:
int legacyId = oldObject.Id;
int newId = GetNewIdFromLegacyId(legacyId);
newObject.LegacyId = legacyId;
newObject.NewId = newId;
This is a micro-isolation of responsibilities: getting Id values and object initialization. This may seem nitpicking, but Single Responsibility (the S of SOLID) is one of the most important design principles and it can be applied at any level to make code better maintainable. It might lead you to separating the code in two parts that you can (unit) test separately.
I've got a module setup to be like a library for a few other scripts. I can't figure out how to get a class declaration into the script scope calling Import-Module. I tried to arrange Export-Module with a -class argument, like the -function, but there isn't a -class available. Do I just have to declare the class in every script?
The setup:
holidays.psm1 in ~\documents\windows\powershell\modules\holidays\
active script calls import-module holidays
there is another function in holidays.psm1 that returns a class object correctly, but I don't know how to create new members of the class from the active script after importing
Here is what the class looks like:
Class data_block
{
$array
$rows
$cols
data_block($a, $r, $c)
{
$this.array = $a
$this.rows = $r
$this.cols = $c
}
}
PSA: There is a known issue that keeps old copies of classes in memory. It makes working with classes really confusing if you don't know about it. You can read about it here.
using is Prone to Pitfalls
The using keyword is prone to various pitfalls as follows:
The using statement does not work for modules not in PSModulePath unless you specify the module's full path in the using statement. This is rather surprising because although a module is available via Get-Module the using statement may not work depending on how the module was loaded.
The using statement can only be used at the very beginning of a "script". No combination of [scriptblock]::Create() or New-Module seems overcome this. A string passed to Invoke-Expression seems to act as a sort of standalone script; a using statement at the beginning of such a string sort of works. That is, Invoke-Expression "using module $path" can succeed but the scope into which the contents of the module are made available seems rather inscrutable. For example, if Invoke-Expression "using module $path" is used inside a Pester scriptblock, the classes inside the module are not available from the same Pester scriptblock.
The above statements are based on this set of tests.
ScriptsToProcess Prevents Access to Private Module Functions
Defining a class in a script referred to by the module manifest's ScriptsToProcess seems at first glance to export the class from the module. However, instead of exporting the class, it "creates the class in the global SessionState instead of the module's, so it...can't access private functions". As far as I can tell, using ScriptsToProcess is like defining the class outside the module in the following manner:
# this is like defining c in class.ps1 and referring to it in ScriptsToProcess
class c {
[string] priv () { return priv }
[string] pub () { return pub }
}
# this is like defining priv and pub in module.psm1 and referring to it in RootModule
New-Module {
function priv { 'private function' }
function pub { 'public function' }
Export-ModuleMember 'pub'
} | Import-Module
[c]::new().pub() # succeeds
[c]::new().priv() # fails
Invoking this results in
public function
priv : The term 'priv' is not recognized ...
+ [string] priv () { return priv } ...
The module function priv is inaccessible from the class even though priv is called from a class that was defined when that module was imported. This might be what you want, but I haven't found a use for it because I have found that class methods usually need access to some function in the module that I want to keep private.
.NewBoundScriptBlock() Seems to Work Reliably
Invoking a scriptblock bound to the module containing the class seems to work reliably to export instances of a class and does not suffer from the pitfalls that using does. Consider this module which contains a class and has been imported:
New-Module 'ModuleName' { class c {$p = 'some value'} } |
Import-Module
Invoking [c]::new() inside a scriptblock bound to the module produces an object of type [c]:
PS C:\> $c = & (Get-Module 'ModuleName').NewBoundScriptBlock({[c]::new()})
PS C:\> $c.p
some value
Idiomatic Alternative to .NewBoundScriptBlock()
It seems that there is a shorter, idiomatic alternative to .NewBoundScriptBlock(). The following two lines each invoke the scriptblock in the session state of the module output by Get-Module:
& (Get-Module 'ModuleName').NewBoundScriptBlock({[c]::new()})
& (Get-Module 'ModuleName') {[c]::new()}}
The latter has the advantage that it will yield flow of control to the pipeline mid-scriptblock when an object is written to the pipeline. .NewBoundScriptBlock() on the other hand collects all objects written to the pipeline and only yields once execution of the entire scriptblock has completed.
I found a way to load the classes without the need of "using module".
In your MyModule.psd1 file use the line:
ScriptsToProcess = #('Class.ps1')
And then put your classes in the Class.ps1 file:
class MyClass {}
Update: Although you don't have to use "using module MyModule" with this method you still have to either:
Run "using module MyModule"
Or run "Import-Module MyModule"
Or call any function in your module (so it will auto import your module on the way)
Update2: This will load the Class to the current scope so if you import the Module from within a function for example the Class will not be accessible outside of the function. Sadly the only reliable method I see is to write your Class in C# and load it with Add-Type -Language CSharp -TypeDefinition 'MyClass...'.
According to here and here, you can use classes defined in your module by doing the following in PowerShell 5:
using module holidays
The using statement is the way to go if it works for you. Otherwise this seems to work as well.
File testclass.psm1
Use a function to deliver the class
class abc{
$testprop = 'It Worked!'
[int]testMethod($num){return $num * 5}
}
function new-abc(){
return [abc]::new()
}
Export-ModuleMember -Function new-abc
File someScript.ps1
Import-Module path\to\testclass.psm1
$testclass = new-abc
$testclass.testProp # Returns 'It Worked!'
$testclass.testMethod(500) # Returns 2500
$testclass | gm
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
testMethod Method int testMethod(System.Object num)
ToString Method string ToString()
testprop Property System.Object testprop {get;set;}
You pretty much cannot. According to about_Classes help:
Class keyword
Defines a new class. This is a true .NET Framework type. Class members are public, but only public within the module scope. You can't refer to the type name as a string (for example, New-Object doesn't work), and in this release, you can't use a type literal (for example, [MyClass]) outside the script/module file in which the class is defined.
This means, if you want to get yourself a data_block instance or use functions that operate those classes, make a function, say, New-DataBlock and make it return a new data_block instance, which you can then use to get class methods and properties (likely including static ones).
This certainly does not work as expected.
The idea in PowerShell 5 is that you can define your class in a separate file with a .psm1 extension.
Then you can load the definition with the command (e.g.):
using module C:\classes\whatever\path\to\file.psm1
This must be the first line in your script (after comments).
What causes so much pain is that even if the class definitions are called from a script, the modules are loaded for the entire session. You can see this by running:
Get-Module
You will see the name of the file you loaded. No matter if you run the script again, it will not reload the class definitions! (It won't even read the psm1 file.) This causes much gnashing of teeth.
Sometimes - sometimes - you can run this command before running the script, which will reload the module with refreshed class definitions:
Remove-Module file
where file is the name without path or extension. However, to save your sanity I recommend restarting the PowerShell session. This is obviously cumbersome; Microsoft needs to clean this up somehow.
I've encountered multiple issues regarding PowerShell classes in v5 as well.
I've decided to use the following workaround for now, as this is perfectly compatible with .NET and PowerShell:
Add-Type -Language CSharp -TypeDefinition #"
namespace My.Custom.Namespace {
public class Example
{
public string Name { get; set; }
public System.Management.Automation.PSCredential Credential { get; set; }
// ...
}
}
"#
The benefit is that you don't need a custom assembly to add a type definition. You can add the class definition inline in your PowerShell scripts or modules.
The only downside is that you will need to create a new runtime to reload the class definition after is has been loaded for the first time (just like loading assemblies in a C#/.NET domain).
The way I've worked around this problem is to move your custom class definition into an empty .ps1 file with the same name (like you would in Java/C#), and then load it into both the module definition and your dependent code by dot sourcing. I know this isn't great, but to me it's better than having to maintain multiple definitions of the same class across multiple files...
To update class definitions while developing, select the code for the class and press F8 to run the selected code. It is not as clean as the -Force option on the Import-Module command.
Seeing as using Module doesn't have that option and Remove-Module is sporadic at best, this is the best way I have found to develop a class and see the results without having to close down the PowerShell ISE and start it up again.
A surprising & cumbersome limitation of using module appears to be that any classes to expose outside of a module MUST be in the module's psm1 file itself.
A class definition to expose outside the module cannot be 'dotsourced' into the psm1 file from a separate ps1 file in the module
...this is as per the docs since v5.1 (to at least 7.2):
The using module statement imports classes from the root module
(ModuleToProcess) of a script module or binary module. It does not
consistently import classes defined in nested modules or classes
defined in scripts that are dot-sourced into the module. Classes that
you want to be available to users outside of the module should be
defined in the root module.
So therefore, it seems the simplest options (as discussed in other answers) are:
If you only need to reference class instances outside of its defining module, create public functions to return class instances:
function Get-MyModulesClass { [MyModuleClass]::New() }
To reference a class type outside of the module (eg specifing a function argument's type), the class must have been defined directly in the psm1 file of the module, and this psm1 file must have been included in your external script via using module (eg using module <relativePathToModulePsm1File>).
...and of course what doesn't help when figuring all this out is that classes don't reload so you need start a new powershell session every time you make a change to the classes.
Example Module
/MyLibaryModule/MyPrivateClass.ps1:
class MyPrivateClass {
[void] Test(){ Write-Host "Accessed private class methods!"}
}
/MyLibaryModule/MyLibraryModule.psm1
class MyPublicClass {} # Exposed classes MUST be defined in this file
. $PSScriptRoot\MyPrivateClass.ps1
function Get-MyPrivateClassInstance { [MyPrivateClass]::new()}
/ExampleScript.ps1
using module .\MyLibraryModule\MyLibraryModule.psm1
[MyPublicClass]$myVar1 # Works
[MyPrivateClass]$myVar2 # Errors
Import-Module .\MyLibraryModule\MyLibraryModule.psm1
$object = Get-MyPrivateClassInstance
$object.GetType().Name
$object.Test() # works
Output
InvalidOperation:
Line |
5 | [MyPrivateClass]$myVar2 # Errors
| ~~~~~~~~~~~~~~
| Unable to find type [MyPrivateClass].
MyPrivateClass
Accessed private class methods!
I'm building a MEF-based plugin-centric WPF application and I'm facing an issue with GetExports, maybe it's just my ignorance but I find an odd behaviour. I have a number of exported parts, all derived from 2 different interfaces (let's name them A and B), but all marked with the same metadata attribute X. So I have code like:
[Export(typeof(A))]
[TheXAttributeHere...]
public class SomePart1 : A { ... }
for each part, and the same for classes implementing B:
[Export(typeof(B))]
[TheXAttributeHere...]
public class SomePart2 : B { ... }
Now, when I try getting all the parts implementing A and decorated by attribute X with some values, MEF returns not only the A-implementing parts, but ALSO the B-implementing parts. So, when I expect to deal with A-objects I get a B, whence a cast exception.
In the real world, interfaces are named IItemPartEditorViewModel and IItemPartEditorView, while their common attribute is named ItemPartEditorAttribute and exposes a PartType string property on which I do some filtering. My code to get parts is thus like e.g.:
var p = (from l in container.GetExports<IItemPartEditorViewModel, IItemPartEditorMetadata>()
where l.Metadata.PartType == sPartType
select l).FirstOrDefault();
When looking for IItemPartEditorViewModel whose PartType is equal to some value, I get the IItemPartEditorView instead of IItemPartEditorViewModel implementing object. If I comment out the attribute in the IItemPartEditorView object instead, I correctly get the IItemPartEditorViewModel implementing object.
Update the suggested "templated" method was used, but I mistyped it here as I forgot to change lessthan and greaterthan into entities. Anyway, reviewing the code I noticed that in the attribute I had "ViewModel" instead or "View" for the interface type, so this was the problem. Shame on me, sorry for bothering :)!
I think I'd need to see more of the code to know for sure what's going on. However, I'd suggest you call GetExports like this:
// Get exports of type A
container.GetExports<A>();
// Get exports of type B
container.GetExports<B>();
Then do your filtering on the list returned. This will probably fix the cast issues you are having. I'd also be interested in seeing the code for the custom metadata attribute. If it derives from ExportAttribute for example, that might be part of the problem.