Nov 09 2022 07:09 AM - edited Nov 14 2022 01:29 AM
I have a .NET library and I want to call it's function/constructor from PowerShell. In this case expecting it to print a HyperLink on console.
Here is the schema for the Log class
In C#, it is called as
Log.Trace(new CommentTrace("Comment message") { XmlAnnotation="<SupportingInfo><Item /></SupportingInfo>" });
Log.Trace(new CommentTrace("Error message") { XmlAnnotation
= "<SupportingInfo>"
+ "<Item Name=\"Test Wiki\" Value=\"htpps://xyz.com\" Type =\"url\" />"
+ "</SupportingInfo>"
});
How do I call it in powershell?
Trying
[LOG]::Trace((New-Object CommentTrace 'URL Argument' -Property @{ XmlAnnotation="<SupportingInfo><Item Name='URL Hyperlink' Value='$URLValue' Type ='url'></item></SupportingInfo>"} ))
[LOG]::Trace((New-Object CommentTrace 'URL Argument' -Property @{ XmlAnnotation="<SupportingInfo><Item Name='URL Hyperlink' Value='$URLValue' Type ='url'></item></SupportingInfo>"} ))
However it ends up ignoring the XMLAnnotation property entirely.
Expected: to consider the XMLAnnotation passed and print the hyperlink
How to achieve get this working in powershell.
And how to learn converting .NET OOOPs code in powershell
Nov 11 2022 04:18 AM
Without being familiar with the LogTrace class you reference, and without seeing the definition behind the TraceImpl method, it's hard to be specific. I'd also wager this isn't the best place to ask simply because most of the enquiries in here are more of the basic "how to use PowerShell" variety.
For my part, based on the above limitations, all I can put forward is a loose analogy that is structurally similar to yours.
Here is the reductionist C# code, where - roughly:
using System;
namespace FooLibrary
{
public class SomeRandomClass
{
public string Message;
public string Annotation;
public SomeRandomClass(string message)
{
Message = message;
}
public override string ToString()
{
if (!string.IsNullOrWhiteSpace(Annotation))
return ($"{ Message } -> { Annotation }");
else
if (!string.IsNullOrWhiteSpace(Message))
return (Message);
else
return (null);
}
}
public struct SomeRandomStruct
{
internal SomeRandomClass RandoClass;
public string Annotation
{
set
{
RandoClass.Annotation = value;
}
}
public SomeRandomStruct(string message)
{
RandoClass = new SomeRandomClass(message);
}
}
public static class SomeRandomConsumer
{
public static void Print(SomeRandomStruct randoStruct)
{
Console.WriteLine(randoStruct.RandoClass);
}
}
}
Compiling this and importing it using Add-Type, I've produced the following four examples:
I'm going to focus on the Annotation member from the above examples as the analogy for your XmlAnnotation.
Like the constructor from your CommentTrace struc, I'm initialising "Message" in the underlying RandoClass variable but not "Annotation".
You can see in the output from this first example that PowerShell can only see the members from the struc, which in this case is only Annotation, which in turn has no getter, hence the null value for Annotation.
Not much to say here. The error's just confirming that trying to read Annotation generates the expected "forget about it" response from PowerShell since no getter is defined in the struc - the same as your struc.
So, now we move on to looking at your static Trace method, which in my case is the Print method. At this point, my SomeRandomStruc (your CommentTrace) struc is largely irrelevant, as the output string is really coming from the underlying SomeRandomClass (your LogTrace) via the RandoClass (your LogTrace) variable within the struc.
No surprises here. Because Annotation is still null, the output only features Message.
And now we finally get to the scenario most relevant to your question, and the only important takeaway here is that it works using exactly the same PowerShell command line structure you have used.
Having use "-Property @{ Annotation = "FunkyTown" }", my output does indeed reflect the fact that the property specification has worked.
I don't think you're running into issues with the command line you've used within PowerShell - that looks fine to me and works as shown above in Example 4.
I can only conclude there is something wrong with the C# implementation.
However, as I pointed out at the start, I've had to generalise a lot given the absence of important artefacts, so if I've missed something in the process, my apologies. By all means fill in the gaps where I've had to make assumptions.
Leaving out the getter isn't a great idea when it comes to PowerShell, as the general rule of thumb is that if you're going to have a property expose at all then the value really should be readable. In this scenario, we're talking about Annotation within the CommentTrace struc.
PowerShell has got a different audience and purpose compared to more formal, structured languages like C#. If you put the two in a Venn diagram, there'd certainly be good overlap, but in PowerShell there's more of a bent towards ad hoc engagement and intuitiveness, meaning things like properties that can never - by design - contain a value are out of place in PowerShell despite making perfect sense within C#.
Using PowerShell nomenclature, a method named something like "void SetXmlAnnotation" would be more intuitive to the PowerShell community, who frequently don't have a formal programming background.
Cheers,
Lain