I'm running C# PowerShell code on a remote system and need to get the value of a local variable. PowerShell has a cmdlet named Get-Variable which I'm trying to use. This is my code for trying to fetch the relevant collection of PSVariables (which obviously should contain just one):
psShell.AddScript($"$text = 'someValue'");
psShell.Invoke();
psShell.Commands.Clear();
psShell.AddCommand("Get-Variable")
.AddParameter("Name", "text");
var v = psShell.Invoke<PSVariable>();
Problem is on the last line, I get the following exception:
Cannot convert the "System.Management.Automation.PSVariable" value of type "Deserialized.System.Management.Automation.PSVariable" to type "System.Management.Automation.PSVariable".
Anyone know how to solve this ?
Also, I know of the SessionStateProxy method mentioned on StackOverflow, but as this post of mine shows, it doesn't work for my scenario for some reason.
When PowerShell remoting is involved, only a handful of well-known types deserialize with type fidelity, System.Management.Automation.PSVariable not being among them.
Instances of all other types deserialize as method-less emulations of the original objects, as [psobject] instances with properties containing static copies of the original property values.
In PowerShell, these instances report their type name as the original type name prefixed with Deserialized.
See this answer for background information.
The simplest way to handle such objects is via the DLR:
dynamic v = psShell.Invoke();
Then you can access properties as usual (albeit with runtime binding), e.g., v.Name.
Related
I have an AnonymousType object that contacts two fields with their values. How can I access the value of these fields?
Ex:
SourceTypeObject { Source_Type_Id = 1, Source_Type_Name = "bibliography" }
I need to do something like : SourceTypeObject.Source_Type_Id
Is that possible?
EDIT:
Here's what I get if I tried to access the property directly:
Yes, this is the exact purpose of anonymous types. The only thing that might prevent you from doing so is if you passed the anonymous type around as a parameter with type "object". This would hide information about the anonymous type, and it would look like just any old object then.
The only recourse if this is the case is to use reflection, which is slow and awkward. Anonymous types are a meant to be a very "local" phenomenon, and if you find yourself wanting to use them elsewhere in the program, it's worth the time to promote it to a real type.
EDIT: In response to the image you posted, assuming the array is declared locally just outside of view, try to replace the object SourceTypeObject with var SourceTypeObject. This allows it to infer the anonymous type instead of being told that it's an object.
I need to loop over a List<dynamic> objects.
The list's objects all have values, but for some reason, I am not able to access any of the dynamic object fields. Below is a screenshot of my debug window:
There you can see the object contains fields (such Alias, Id, Name, etc).
I tried both casting it to a IDictionary<string, object> and ExpandoObject, to no avail. I did not face such a thing before: failing to access existing fields in a dynamic object when they exist.
What is wrong here?
The code is throwing a Microsoft.CSharp.RuntimeBinder.RuntimeBinderException with a message stating {"'object' does not contain a definition for 'Name'"}.
The list was created adding anonymously-typed objects, like this:
return new List<dynamic>(fields.Select(field => new
{
Id = field.Id,
Alias = field.Alias,
Name = field.Name,
Type = field.Type,
Value = field.Value,
SortOrder = field.SortOrder
}));
where fields is an ICollection<Field>, a strongly-typed collection.
The telling part is the exception:
{"'object' does not contain a definition for 'Name'"}.
This indicates that the runtime binder was not actually capable of accessing the type you're passing in dynamic (since dynamic does actually enforce visibility rules).
The most likely cause of this is that you're creating the anonymous type in a different assembly from the one where you're subsequently reading it - since anonymous types are declared internal, the consuming assembly cannot access it, causing the error message above.
Contrast with the usual case of runtime binder exceptions:
'<>f__AnonymousType0< string >' does not contain a definition for 'Name'
EDIT:
A possible solution to the problem is to use the InternalsVisibleToAttribute on the assembly containing the anonymous type. However, this is code smell - just like any other use of InternalsVisibleToAttribute or internal itself.
A better way would be to make sure you don't actually pass anonymous types over assembly boundaries - after all, they shouldn't even be used outside of the method they originated from; the fact that they are is basically an implementation detail of .NET - they didn't have another way to do the same thing. This could change in future versions, making the InternalsVisibleToAttribute solution doubly unreliable.
The way your code is using dynamic suggests that your team has flawed assumptions about how dynamic works and how it's supposed to be used. Note how the actual runtime type of List<dynamic> is actually List<object>. The same goes for arguments of type dynamic (which are again just object, albeit marked with DynamicAttribute). And in fact, that really is what dynamic is - it's a way to handle runtime dynamic dispatch - it's not a property of the type or anything, it's just the way you actually invoke whatever you're trying to invoke. For C#, dynamic allows you to skip most of the compiler checks when working with those dynamic types, and it generates some code to handle the dispatch for you automatically, but all of that only happens inside the method where you actually use the dynamic keyword - if you used List<object>, the end result would be exactly the same.
In your code, there's no reason not to use simple static types. Dynamic typing doesn't really give you any benefits, apart from the effort to code the types themselves. If your co-workers don't like that, well, they should present a better solution - the problem is quite obvious, and it's something you need to deal with.
Much worse, it explicitly hides all context, all the type information. That's not something you want in an API, internal or not! If you want to hide the concrete types being used, why not - but you should still expose an interface instead. I suspect this is the reason why anonymous types can't implement interfaces - it would encourage you to go entirely the wrong way.
I have a dbf file (dBase) that I want to read, put each row into a single list (since a row represents data about one shapefile object), and then be able to modify the list (e.g., convert fields which represent the name to a string). This means that the datatype need to be able to hold both Ints, strings, bool and so on, and add items to, it. In python I could do this with lists, but since sets cant be modified, I cant use them.
This sounds like a (exact) duplicate to Alternative to Tuples,
but it isn't. These questions are based on the assumption that you know which objects you want beforehand; I don't.
I'm on .NET 4.5, btw.
Use dynamic - it is a perfect use case for it:
Visual C# 2010 introduces a new type, dynamic. The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object. At compile time, an element that is typed as dynamic is assumed to support any operation. Therefore, you do not have to be concerned about whether the object gets its value from a COM API, from a dynamic language such as IronPython, from the HTML Document Object Model (DOM), from reflection, or from somewhere else in the program. However, if the code is not valid, errors are caught at run time.
If you want to be able to easily add properties at runtime and change their types, you can use ExpandoObject with dynamic, for example:
dynamic expando = new ExpandoObject();
expando.SomeProperty = "1234";
Console.WriteLine(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty.GetType().FullName); // string
expando.SomeProperty = int.Parse(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty.GetType().FullName); // int
Have you tried using the dynamic type?
While codeing for a project. i got in a situation where i need to call the method or the member of a type via string expresssion. for example i want to get the result of DateTime.Today value into a result box or a variable..
Is there any way to call the function or a member of a class from the string expression.?
Here are some of the examples what i am looking for.
DateTime.Now
DateTime.Today.ToString("dd-MM-yyyy")
Environment.SpecialFolder.ApplicationData
Above are some of the expression user may pass into a textbox and get the result by invoking them thru any button.
Here you can find an Valid solution with on the fly compiling link here:
execute c# code at runtime from code file
this should solve your Problem, but it is not really secure.
Depence on the Range of Code execution or "inspection", i would create own commands/rules, to be on the "Save" Side, and prevent the possibility of injecting (evil) Code.
I hope this helps.
If the first part of the expression is always the type, you can use reflection to create the type. Something like this, for example:
string theType = "System.DateTime";
Type t = Type.GetType(theType);
Object o = Activator.CreateInstance(t);
But to invoke the method/property, you would have to cast the object to the type, but you don't know the type until runtime, so that will be problematic.
I think you may want to reconsider your approach. Maybe you can give the user an interface where they can choose some options from a list in order to build their expression. For example, let them choose DateTime, Environment, etc. and then based on that selection you give them other options to choose (e.g. Now if they selected DateTime, etc.).
Free form parsing an expression like you're trying to do is going to be difficult and hackish at best.
I am trying to serialize a large object, this has worked for months if not years now and a recent revision has caused this bug to occur in older files.
When re-serializing them I receive a message saying that TypeLoadExceptionHolder is not marked as 'Serializable'. I have set a breakpoint immediately before the serialization call and cannot seem to find any reference that is of that type. Is there anyway to 'scan' the object I am trying to serialize and see where the reference to the TypeLoadExceptionHolder is?
There are a number of scenarios that can trigger this type of exception. A few more common are here and here.
(Summarizing from the above links) In a nutshell binary serialization doesn't throw exceptions when a type cannot be serialized. Instead, it replaces the unserializable type with TypeLoadExceptionHolder type. On top of not being not very well documented, it's reason for being used is even less so.
You may be stuck with manually figuring out what has changed in the object that you are trying to serialize. Specifically, look for:
Namespace changes.
Member name changes.
Member data type changes.