How can I access an internal class from an external assembly? - c#

Having an assembly which I cannot modify (vendor-supplied) which have a method returning an object type but is really of an internal type.
How can I access the fields and/or methods of the object from my assembly?
Keep in mind that I cannot modify the vendor-supplied assembly.
In essence, here's what I have:
From vendor:
internal class InternalClass
public string test;
end class
public class Vendor
private InternalClass _internal;
public object Tag {get{return _internal;}}
end class
From my assembly using the vendor assembly.
public class MyClass
{
public void AccessTest()
{
Vendor vendor = new Vendor();
object value = vendor.Tag;
// Here I want to access InternalClass.test
}
}

I see only one case that you would allow exposure to your internal members to another assembly and that is for testing purposes.
Saying that there is a way to allow "Friend" assemblies access to internals:
In the AssemblyInfo.cs file of the project you add a line for each assembly.
[assembly: InternalsVisibleTo("name of assembly here")]
this info is available here.

Without access to the type (and no "InternalsVisibleTo" etc) you would have to use reflection. But a better question would be: should you be accessing this data? It isn't part of the public type contract... it sounds to me like it is intended to be treated as an opaque object (for their purposes, not yours).
You've described it as a public instance field; to get this via reflection:
object obj = ...
string value = (string)obj.GetType().GetField("test").GetValue(obj);
If it is actually a property (not a field):
string value = (string)obj.GetType().GetProperty("test").GetValue(obj,null);
If it is non-public, you'll need to use the BindingFlags overload of GetField/GetProperty.
Important aside: be careful with reflection like this; the implementation could change in the next version (breaking your code), or it could be obfuscated (breaking your code), or you might not have enough "trust" (breaking your code). Are you spotting the pattern?

I would like to argue one point - that you cannot augment the original assembly - using Mono.Cecil you can inject [InternalsVisibleTo(...)] to the 3pty assembly. Note there might be legal implications - you're messing with 3pty assembly and technical implications - if the assembly has strong name you either need to strip it or re-sign it with different key.
Install-Package Mono.Cecil
And the code like:
static readonly string[] s_toInject = {
// alternatively "MyAssembly, PublicKey=0024000004800000... etc."
"MyAssembly"
};
static void Main(string[] args) {
const string THIRD_PARTY_ASSEMBLY_PATH = #"c:\folder\ThirdPartyAssembly.dll";
var parameters = new ReaderParameters();
var asm = ModuleDefinition.ReadModule(INPUT_PATH, parameters);
foreach (var toInject in s_toInject) {
var ca = new CustomAttribute(
asm.Import(typeof(InternalsVisibleToAttribute).GetConstructor(new[] {
typeof(string)})));
ca.ConstructorArguments.Add(new CustomAttributeArgument(asm.TypeSystem.String, toInject));
asm.Assembly.CustomAttributes.Add(ca);
}
asm.Write(#"c:\folder-modified\ThirdPartyAssembly.dll");
// note if the assembly is strongly-signed you need to resign it like
// asm.Write(#"c:\folder-modified\ThirdPartyAssembly.dll", new WriterParameters {
// StrongNameKeyPair = new StrongNameKeyPair(File.ReadAllBytes(#"c:\MyKey.snk"))
// });
}

Reflection.
using System.Reflection;
Vendor vendor = new Vendor();
object tag = vendor.Tag;
Type tagt = tag.GetType();
FieldInfo field = tagt.GetField("test");
string value = field.GetValue(tag);
Use the power wisely. Don't forget error checking. :)

In .NET 5 it's possible to add InternalsVisibleToAttribute to your .csproj:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>Core.Tests</_Parameter1>
</AssemblyAttribute>
</ItemGroup>

Well, you can't. Internal classes can't be visible outside of their assembly, so no explicit way to access it directly -AFAIK of course.
The only way is to use runtime late-binding via reflection, then you can invoke methods and properties from the internal class indirectly.

Related

Converting DeclaredAccessibility to C# string in Roslyn

I want to implement interfaces in my code generator, so I need to convert Microsoft.CodeAnalysis.Accessibility (i.e. from ISymbol.DeclaredAccessibility) to their represented modifier keywords.
This enum is used in code analysis APIs for describing access modifiers of a class or its members.
For instance, if you have public void MyMember() its ISymbol.DeclaredAccessibility will be Accessibility.Public.
I need to create such a method declaration, thus I need a way to convert Accessibility.Public to public and so on (take note that just ToLower will work only for simple cases, it won't generate protected internal).
What is the correct way to do it?
With the SyntaxFacts.GetText(Accessibility) Method:
string publicKeyword = SyntaxFacts.GetText(Accessibility.Public);
string accessibilityKeyword = SyntaxFacts.GetText(accessibility);
Namespace: Microsoft.CodeAnalysis.CSharp
Assembly: Microsoft.CodeAnalysis.CSharp.dll
Package: Microsoft.CodeAnalysis.CSharp
Available since: v3.0.0
[Theory]
[InlineData(Accessibility.NotApplicable, "")]
[InlineData(Accessibility.Private, "private")]
[InlineData(Accessibility.ProtectedAndInternal, "private protected")]
[InlineData(Accessibility.Protected, "protected")]
[InlineData(Accessibility.Internal, "internal")]
[InlineData(Accessibility.ProtectedOrInternal, "protected internal")]
[InlineData(Accessibility.Public, "public")]
public void Accessibility_To_ModifierKeyword(Accessibility accessibility, string expected)
{
string actual = SyntaxFacts.GetText(accessibility);
actual.Should().Be(expected);
}

How to create an instance of C# class with a property whose setter is private..from F#

So I am working on a F# project, and need to access some C# classes. In particular, one of the C# class looks like this:
class LoginRequest {
public string Scope {get; private set;}
}
Now with C# itself, an instance can be created easily with object initializer: new LoginRequest() {Scope = "all"} for example.
However, I could not figure out a way to create such an instance from F#. Any tips?
For the given example there is no easy (non-reflection, see below) way, i.e. private setters are inaccessible from C# and F#:
new LoginRequest { Scope = "s" }; // CS0272 The property or indexer 'LoginRequest.Scope' cannot be used in this context because the set accessor is inaccessible
LoginRequest(Scope = "s") // error FS0495: The object constructor 'LoginRequest' has no argument or settable return property 'Scope'.
For accessing the private setter, you could use
let r = LoginRequest()
typeof<LoginRequest>.GetProperty("Scope").GetSetMethod(true).Invoke(r, [| "scope" |])
r.Scope // scope
However, I would strongly discourage the use of reflection. The most obvious reason being that you lose compile time safety.

Constant management across assemblies

My team is trying to figure out the best way to manage centralized constants (Read-only static variables probably) across our custom assemblies. We have built a processing architecture where assemblies are dynamically loaded into the runtime. As data goes through our system, some assemblies write information to a dictionary that is then passed to another assembly that will read the data out and process it. As our product matures and our customer needs different processing capabilities, we will need to add new data fields that will be written/read. As of now we have our constants defined in our core dll, but this will not work long term because when we get a new piece of data we will have to recompile the core dll, and in doing so our test team will have to fully regression test the entire application rather than just testing the new functionality provided by the new assembly. Were trying to figure out a way to add new constants and know what data is being written without having to recompile/deploy anything we don't absolutely have to.
We have considered two options:
Create a constants dll, which only holds the constants. When we
need new fields we add (never remove) them to the dll. The down
side of this is that a change to the dll still affects the entire
system, so there may be a need for full regression testing.
Have each assembly expose all of the fields that it reads/writes,
and then during developer integration look for name mismatches. For
example Assembly1 writes (Field1, Field2) and Assembly2 reads
(field1, Filed2), causing a mismatch of (Field1 vs. field1) due to
case sensitivity on dictionary keys. This would keep us from having
a constants assembly, but it would require some additional code for
mismatch verification, and seems to cause some bit of coupling.
Note: when I say constants, I don’t really mean constant. Depending on the solution we end up going with we will probably use read only static.
If anyone has done anything like this, or have any thoughts on a way to accomplish this I will appreciate your input. Our underlying objective is to be able to deliver new functionality by only deploying the new assemblies.
Based on your comment, this really sounds like you should be using DTO classes. Rather than a dictionary with values
dict["PrimaryAddress"] = "123 Someroad St.";
dict["Name"] = "John Doe";`
you should have an object
public class Address
{
public string PrimaryAddress { get; set; }
public string Name { get; set; }
}
....
new Address {
PrimaryAddress = "123 Someroad St.",
Name = "John Doe",
};
For convenience, you can create a base class in your core library which defines some standard behavior for all the classes (for example, public Dictionary<string, string> ConvertToDictionary() for legacy use), and then each assembly can inherit from that to create their own objects. Then the assembly that consumes them can either reference the generating assembly and treat it as the specific type, or it can just treat it as the base form and use the base functionality.
What you can do is create one assembly that is referenced by all other assemblies across your process. (Note that I assume that there actually is only one process in your application).
This assembly will expose a class to hold these "constants". Let's call it a session.
Here is an implementation we use in one of our projects:
//Defined in Dll appshared.dll
public static class MyApplication
{
static AppSession appSession = new AppSession();
public interface IAppSession
{
Object this[string key]
{
get;
set;
}
};
sealed class AppSession : IAppSession
{
Dictionary<String, Object> _session = new Dictionary<string, object>();
public AppSession()
{
}
public Object this[string key]
{
get
{
Object ret = null;
lock (_session)
{
_session.TryGetValue(key, out ret);
}
return ret;
}
set
{
if (key == null)
throw new ArgumentNullException();
try
{
lock (_session)
{
if (value != null)
_session[key] = value;
else
_session.Remove(key);
}
}
catch (Exception eX)
{
}
}
}
};
public static IAppSession Session
{
get
{
return appSession;
}
}
};
And you can use it as follows:
//In Dll A referencing appshared.dll
MyApplication.Session["Const1"] = 1.0;//Set a global value
//In Dll B referencing appshared.dll
double const1 = (double)MyApplication["Const1"];//Read a global value - const1 will have the value set by Dll A
//In Dll C referencing appshared.dll
MyApplication.Session["Const1"] = null;//Delete a global value;
You can of course store any kind of data you want. You can easily modify it not to be case sensitive.
We also have more a complex session object that can synchronize the values with configuration files so the "Constants" are stored across executions. However since you didn't mention you need such capability this simple class should work just fine for you.

C# plugin architecture question

I'm working on a system monitoring application similar to Nagios in C#. I have a plugin interface defined as:
public interface IPlugin
{
PluginResult Execute();
}
Each plugin, depending on its functionality, will have a variable number of arguments. As an example, a ping plugin might take a hostname, # of packets, timeout value, etc. I want the user to be able to define these arguments per service in my user interface, but obviously these arguments won't be known until the application discovers which plugins are available. I'm curious as to how others might design a plugin such that these variable arguments would be discoverable by the application.
Right now, as an example, I've got a ping plugin:
public class PingPlugin : IPlugin
{
private const string RESULT_MESSAGE = "Average ms: {0}; Packet loss: {1}";
private string _hostname;
private int _packets;
private int _timeout;
private int _warningTimeThreshold;
private int _warningLossThreshold;
private int _errorTimeThreshold;
private int _errorLossThreshold;
public PingPlugin(
string hostname,
int packets,
int timeout,
int warningTimeThreshold,
int warningLossThreshold,
int errorTimeThreshold,
int errorLossThreshold)
{
_hostname = hostname;
_packets = packets;
_timeout = timeout;
_warningTimeThreshold = warningTimeThreshold;
_warningLossThreshold = warningLossThreshold;
_errorTimeThreshold = errorTimeThreshold;
_errorLossThreshold = errorLossThreshold;
}
public PluginResult Execute()
{
// execute the plugin
}
}
I thought I might be able to discover the constructor parameters using reflection and present the user with a property grid to allow the configuration of the plugin, but I'm not sure the best way to provide a set of default values with this design. What might some alternatives be?
Have you considered looking at the Managed Extensibility Framework?
Rather than have a Plugin constructor determine the parameters, you might consider something like this:
public interface IPlugin
{
PluginResult Execute(Object parameters);
}
public class PingParameters
{
//Various parameters here, including [Description] and [DisplayName] attributes if you wish
}
public class ParametersTypeAttribute : Attribute
{
public Type Type { get; private set; }
public ParametersTypeAttribute(Type type)
{
Type = type;
}
}
[ParametersType(typeof(PingParameters))]
public class PingPlugin : IPlugin
{
public PluginResult Execute(Object parameters)
{
return Execute((PingParameters) parameters);
}
private PluginResult Execute(PingParameters parameters)
{
//Your execution code here
}
}
This gives you more flexibility for the parameters, as you can add attributes, provide setter validation and even specify designer/converter integration for the property grid. The property grid hooks up directly to the parameters object.
You can apply the [DefaultValue] attribute to the parameters.
In C# for, you can use new syntax for this: int warningLossThreshold = 30,
I voted +1 for the MEF answer too, it will solve many of your problems.
However, if you want to do it without MEF, it seems to me that you are missing some way to have the plugins tell your application via metadata, about the parameters it require.
One possible design could be this: Have an IPluginProvider interface, which your application can discover. This should have a parameterless constructor, so you can easily new up an instance. It should then have methods that return whatever metadata is needed (such as "pretty names" for the parameters, which are required, what are some sensible defaults, and so on). It should then include CreateInstance method, which takes the actual parameters as IDictionary<string,object> and returns the actual IPlugin instance.
I haven't looked at the MEF (will do now).
I had a problem almost identical to yours, I solved it with Attributes.
I have a UI which (calls BL which) uses reflection to show all the available "services" (nothing more than appropriately decorated classes).
When the user selects a "service" further attributes drive the UI. The attribute "schema" is fairly straight forward, and allows for any number of parameters with any name. By introducing constants (with the attribute definition) you can standardise common things like "name" so that your services are consistent.
All the data is then stored in a Key-Value pair table.
The great thing about this is that you can just dump new / modified "service" assemblies in teh bin dir - no extra work required. The only dependency is the attribute definitions assembly - so keep this lean.
Source code is at CodePlex if you want to "steal" some :)

How to fetch object name using reflection in .net?

In .net how do I fetch object's name in the declaring type. For example...
public static void Main()
{
Information dataInformation = new Information();
}
public class Inforamtion
{
//Constructor
public Inforamtion()
{
//Can I fetch name of object i.e. "dataInformation" declared in Main function
//I want to set the object's Name property = dataInformation here, because it is the name used in declaring that object.
}
public string Name = {get; set;}
}
As far as the CLR goes, there's not really a way to determine an object's name. That sort of information is stored (to some extent) in the debugging information and the assembly, but it's not used at runtime. Regardless, the object you're referring to is just a bunch of bytes in memory. It could have multiple references to it with multiple names, so even if you could get the names of all the variables referencing the object, it would be impossible to programmatically determine which one you're looking to use.
Long story short: you can't do that.
That is the variable name, not the object name. It also poses the question: what is the name here:
Information foo, bar;
foo = bar = new Information();
You can't do this for constructors etc; in limited scenarios it is possible to get a variable name via Expression, if you really want:
public static void Main()
{
Information dataInformation = new Information();
Write(() => dataInformation);
}
static void Write<T>(Expression<Func<T>> expression)
{
MemberExpression me = expression.Body as MemberExpression;
if (me == null) throw new NotSupportedException();
Console.WriteLine(me.Member.Name);
}
Note that this relies on the capture implementation, etc - and is generally cheeky.
I don't think this is possible.
But at the first place, why do you need something like this??
With my experience i have realized that if you need something weird from a compiler or a language which is not offered, then (most often) it means that there is something wrong with the approach or the logic.
Please reconsider why are you trying to achieve this.

Categories