'constructor' is not a recognized attribute location - c#

After trying to compile the following code:
public sealed class Program
{
[constructor: CLSCompliant(false)]
public Program()
{
}
}
I am getting the following error:
'constructor' is not a recognized attribute location. Valid attribute locations for this declaration are 'method'. All attributes in this block will be ignored. [Console.NET]csharp(CS0658)
I know that there are the following locations are present: assembly, module, method, parameter, return, etc. So, my guess was that the constructor should be present as well (since we can have a constructor as a target for an attribute as well). But it seems that it is not the case here.
Also, I was not able to find a full list of the recognized attribute locations on the MSDN. So, that would be helpful if someone would provide a link to the list of the locations on the MSDN.
My guess about the presence of the constructor location was based after I met the following code sample in the C# via CLR book:
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
[assembly: CLSCompliant(true)]
[Serializable]
[DefaultMemberAttribute("Main")]
[DebuggerDisplayAttribute("Richter", Name = "Jeff", Target = typeof(Program))]
public sealed class Program
{
[Conditional("Debug")]
[Conditional("Release")]
public void DoSomething() { }
public Program()
{
}
[CLSCompliant(true)]
[STAThread]
public static void Main()
{
// Show the set of attributes applied to this type
ShowAttributes(typeof(Program));
// Get the set of methods associated with the type
var members =
from m in typeof(Program).GetTypeInfo().DeclaredMembers.OfType<MethodBase>()
where m.IsPublic
select m;
foreach (MemberInfo member in members)
{
// Show the set of attributes applied to this member
ShowAttributes(member);
}
}
private static void ShowAttributes(MemberInfo attributeTarget)
{
var attributes = attributeTarget.GetCustomAttributes<Attribute>();
Console.WriteLine("Attributes applied to {0}: {1}",
attributeTarget.Name, (attributes.Count() == 0 ? "None" : String.Empty));
foreach (Attribute attribute in attributes)
{
// Display the type of each applied attribute
Console.WriteLine(" {0}", attribute.GetType().ToString());
if (attribute is DefaultMemberAttribute)
Console.WriteLine(" MemberName={0}",
((DefaultMemberAttribute)attribute).MemberName);
if (attribute is ConditionalAttribute)
Console.WriteLine(" ConditionString={0}",
((ConditionalAttribute)attribute).ConditionString);
if (attribute is CLSCompliantAttribute)
Console.WriteLine(" IsCompliant={0}",
((CLSCompliantAttribute)attribute).IsCompliant);
DebuggerDisplayAttribute dda = attribute as DebuggerDisplayAttribute;
if (dda != null)
{
Console.WriteLine(" Value={0}, Name={1}, Target={2}",
dda.Value, dda.Name, dda.Target);
}
}
Console.WriteLine();
}
}
And the output of this program is the following:
Attributes applied to Program:
System.SerializableAttribute
System.Diagnostics.DebuggerDisplayAttribute
Value=Richter, Name=Jeff, Target=Program
System.Reflection.DefaultMemberAttribute
MemberName=Main
Attributes applied to DoSomething:
System.Diagnostics.ConditionalAttribute
ConditionString=Release
System.Diagnostics.ConditionalAttribute
ConditionString=Debug
Attributes applied to Main:
System.CLSCompliantAttribute
IsCompliant=True
System.STAThreadAttribute
Attributes applied to .ctor: None
The output makes it clear that a constructor is treated differently from the class and method. And since there are locations class and method, the constructor location is expected by me to be present as well.
I need this solely for the learning purposes.

Attribute targets list present in two places:
limit what an attribute can be applies to (via AttributeUsageAttribute)
disambiguate what the attribute applies to in each particular case (via "Attribute targets
")
So why we'd have "method" but not "constructor" targets (my interpretation, I'm not aware of an official reasoning):
"method" applies to methods and properties. It includes constructor as a special variation of a method. So there is a way to allow an attribute to be used on a constructor and not on an assembly or a field.
when attribute applied to a constructor there is no other possible choices for default "method" target as a constructor matches only "method" option from the list of targets (unlike auto-property for example where attribute can be considered as targeting "method" or "property" or even "field")
presumably there is no useful case where attribute must be restricted to just constructors.
Side note: since attributes by themselves generally don't do anything attribute targets are mainly to limit potential cases where attribute is set but impacts nothing. If you want to "target" just constructors some good naming may be enough. If you really want to limit to just constructors you can check all loaded types for improper use of your custom attribute at startup/first need to check for your custom attribute.

Related

How to use nameof to get the fully qualified name of a property in a class in C# Attributes?

I am using Foolproof library in ASP.Net MVC project and in some cases I need to check a property within a member class of my model using attribues .
For example I have a user class which has a property of type Address and I need to check for the City in the Address.
The attributes need to have the name of the property in a dot notation for my example you could say "Address.City".
Of course this suffers from refactoring issues if I need to change either names later on (Address or City)
I need to use nameof for that purpose and of course if I use it like this :
nameof(Address.City)
it will produce City Only.
I need nameof because it produces constant values that are allowed in attributes.
I found that the reference tells it is possible but not how.
https://msdn.microsoft.com/en-us/library/dn986596.aspx
in remarks section it says:
If you need to get the fully-qualified name, you can use the typeof expression along with nameof.
but I couldn't find any place to tell how to do this.
Can anyone help, please?
Thanks in advance for your time and effort.
Update : October-2019
As I looked up the documentation again they removed the above statement and replaced it with.
As the preceding example shows, in the case of a type and a namespace, the produced name is usually not fully qualified.
After a bit of digging I found that this issue has been discussed already upon developing this feature in here
https://roslyn.codeplex.com/discussions/552376
and specially in here
https://roslyn.codeplex.com/discussions/552377
for the comment by MgSam
As it is proposed, I can imagine something like this happening to get a fully qualified name: BindToFullyQualifiedName(nameof(Microsoft) + "." + nameof(Microsoft.Data) + "." + nameof(Microsoft.Data.Entities) + "." + nameof(Microsoft.Data.Entities.EntityObject));
The answer was
I think typeof(EntityObject).FullName is fully sufficient in your
case.
Which concluded the discussion with no further comments on another way to do this.
Unfortunately this means there is no way to user nameof and get the fully qualified name directly for usage in Attributes.
Probably this is the end of it and I suppose Microsoft should change their documentation to make it more clear and precise.
So I ran into a similar issue and found two workable solutions:
If you want to have the namespaces as well just include them in the expression sent to either full name implementation
First:
public ref struct FullNameOf<T>
{
string _fullName;
public FullNameOf(T _, [CallerArgumentExpression("_")] string fullName = "" )
{
_fullName = fullName;
}
public static implicit operator string(FullNameOf<T> obj)
=> obj._fullName;
}
Second:
public static class FullName
{
public static string Of<T>( T _, [CallerArgumentExpression( "_" )] string fullName = "" )
=> fullName;
}
The usage would look something like this:
public class This
{
public class Is
{
public class A
{
public class Very
{
public class Nested
{
public class Property
{
public static string Here = string.Empty;
}
}
}
}
}
}
Console.WriteLine( $"nameof: {nameof(This.Is.A.Very.Nested.Property.Here) }" );
Console.WriteLine( $"fullnameof: { new FullNameOf<string>(This.Is.A.Very.Nested.Property.Here) }" );
Console.WriteLine( $"fullnameof func: {FullName.Of( This.Is.A.Very.Nested.Property.Here )}" );
The output is:
nameof: Here
fullnameof: This.Is.A.Very.Nested.Property.Here
fullnameof func: This.Is.A.Very.Nested.Property.Here
Another options is to make it into a static function like:
If you don't want to specify a "reference" type (not 'reference type' in the C# sense) to get your target namespace (why should you?), and to save putting a string of nameof operators separated by ., then you can include the "base" namespace by getting the assembly name if it follows the default convention and is named the same as your default namespace, as thus:
$"{Assembly.GetExecutingAssembly().GetName().Name}.{nameof(Level1Namespace)}.{nameof(Level2Namespace)}"
This will at least save you some code, and protect you against refactors where you change the assembly name or even move an entire hierarchy of classes to another assembly, but it of course won't protect against changes within the namespace hierarchy itself. To protect against that, then I think you will indeed need a "reference" type such as perhaps an abstract class or interface that all other classes in the desired namespace inherit, and then apply the accepted answer solution to it.
Inspired by #Ignaz503's answer I came up with an extension method that works in C# 10 or later, and which will give the full name of a type whose name is passed in using the nameof() operator with a fully-qualified name:
public static class FullName {
public static string Of(string _, [System.Runtime.CompilerServices.CallerArgumentExpression("_")] string fullTypeName = "") {
if (fullTypeName.StartsWith("nameof(") && fullTypeName.EndsWith(")")) {
return fullTypeName[7..^1];
}
return fullTypeName;
}
}
Example usage:
Console.WriteLine("Full name: " + FullName.Of(nameof(MyApp.Web.Extensions.MyExtensionClass)));

Pass arguments in to a Type that is supplied to an Attribute

I have an attribute that I am using to decorate object properties with. The attribute identifies the properties as needing validation to be performed on them. I am essentially implementing the Strategy Pattern and building all of the validation (really only about 6 types) in to individual objects that I can use across multiple classes. What I want to do, is provide parameters to the validation classes, without having to create an attribute for each validation object variation.
My attribute looks like this:
[AttributeUsage(AttributeTargets.Property)]
public class ValidationRuleAttribute : Attribute
{
public ValidationRuleAttribute(Type validationRule, string customFailureMessage = "")
{
if (typeof(IValidationRule).IsAssignableFrom(validationRule))
{
this.ValidationRule = string.IsNullOrEmpty(customFailureMessage)
? Activator.CreateInstance(validationRule, customFailureMessage) as IValidationRule
: Activator.CreateInstance(validationRule) as IValidationRule;
}
else
{
throw new ArgumentException(
string.Format(
"ValidationRule attributes can only be used with IValidationRule implementations. The '{0}' Tyoe is not supported.",
validationRule.Name));
}
}
public IValidationRule ValidationRule { get; private set; }
}
As an example, I have a simple StringIsNotNull validation object. I want to expand on it by allowing me to specify a minimum string length requirement. So the StringIsNotEmptyValidation would become StringHasMinimumLengthValidation
public class StringIsNotEmptyValidation : IValidationRule
{
private readonly string customErrorMessage;
public StringIsNotEmptyValidation()
{
}
public StringIsNotEmptyValidation(string customErrorMessage)
{
this.customErrorMessage = customErrorMessage;
}
public string ResultMessage { get; private set; }
public IValidationMessage Validate(System.Reflection.PropertyInfo property, IValidatable sender)
{
string value = property.GetValue(sender).ToString();
// Validate
bool isFailed = string.IsNullOrWhiteSpace(value);
if (isFailed)
{
if (string.IsNullOrEmpty(this.customErrorMessage))
{
DisplayNameAttribute displayName = property.GetCustomAttribute<DisplayNameAttribute>(true);
string errorMessage = displayName == null
? string.Format("You can not leave {0} empty.", property.Name)
: string.Format("You can not leave {0} empty.", displayName.DisplayName);
this.ResultMessage = errorMessage;
return new ValidationErrorMessage(errorMessage);
}
else
{
this.ResultMessage = this.customErrorMessage;
return new ValidationErrorMessage(customErrorMessage);
}
}
this.ResultMessage = string.Empty;
return null;
}
}
Within my model, I decorate my property with the attribute and validation object.
[RepositoryParameter(DbType.String)]
[ValidationRule(typeof(StringIsNotEmptyValidation))]
public string WorkDescription
{
get
{
return this.workDescription ?? string.Empty;
}
set
{
this.SetPropertyByReference(ref this.workDescription, value);
if (this.HasValidationMessageType<ValidationErrorMessage>(this.GetPropertyName(p => p.WorkDescription)))
{
this.Validate();
}
}
}
What I want to do, is write my attribute usage like this:
[ValidationRule(new StringIsNotEmptyValidation(minimumLength: 4))]
Since you can't instance objects in an attribute constructor, I'm forced to provide the attributes in my attribute constructor like this:
[ValidationRule(typeof(StringIsNotEmptyValidation), minLength: 4)]
I don't like this because if I have a ObjectIsNotNull or a StringIsInRange I will need to do two things:
Create a new attribute for each parameter variation (or a lot of overloads)
Set up the validation rule instances within the constructor, which will have varying property names.
The Validation object implements the following interface
public interface IValidationRule
{
string ResultMessage { get; }
IValidationMessage Validate(PropertyInfo property, IValidatable sender);
}
I don't want to bloat my interface with a large number of properties that might be used or might not be used depending on the Rule implementing it. It also makes it difficult to assign attribute params to the rule object.
So my question is how can I provide parameters to the IValidationRule concrete classes, without creating multiple attribute types to facilitate this? This is being used so that I an do cross-object validation. The PropertyInfo passed in to the validation rule is from a cache of PropertyInfo's. I need to keep the amount of reflection used down, otherwise I'd just use attributes for each rule parameter and use reflection on sender to figure out what ranges to use.
Update
After discussing this with Corey, it does indeed appear that attributes are supported in Universal Apps and it is only the DataAnnotations namespace that is missing. In order to get access to the attributes, I had to add a using statement to System.Reflection in order to gain access to a series of extension methods that expose the GetCustomAttribute methods. They are now extension methods and not built in to the Type class.
So I suppose in the end, I can just create my validation logic within the attributes, instead of individual objects. I can't think of any downsides to going this route.
In order to access the attributes in a Universal App, you have to include System.Reflection as a using statement, then access via the GetRuntimeProperties() extension method.
var validationRule = this
.GetType()
.GetRuntimeProperties() // Can be GetRuntimeFields or GetRuntimeMethods as well.
.FirstOrDefault(p => p.GetCustomAttribute<IntegerInRangeAttribute>() != null);
So there are a few options here.
First, and often used, is to have a different attribute for each type of rule you want to process. You are already building classes for each of your rules, so instead of having some encapsulating attribute that instantiates them all just make each rule an attribute:
[StringMinLengthRule(5)]
public string SomeString { get; set; }
Build the validation logic into your attributes - say with a base attribute that does the bulk of the work, calling a virtual method to do the actual validation. Then you can just enumerate the rule attributes and call them from your validation method.
Next, you can have a number of different properties on your attribute that can be set during declaration to provide the properties for your various rules:
[Validation(RuleType.StringMinLength, MinLength = 5)]
public string SomeString { get; set; }
You could still have the rules be processed in the ValidationAttribute itself, or create IValidationRule instances at run-time to process the actual validations. Unfortunately there's nothing to stop you from adding a Validation attribute that sets the wrong properties for the rule type, resulting in errors at run-time when you try to validate an instance.
Finally, something that works but probably shouldn't... and it's kinda ugly:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class ValidationRuleAttribute : Attribute
{
public IValidationRule ValidationRule { get; private set; }
public ValidationRuleAttribute(RuleType type, params object[] parms)
{
if (type == RuleType.NotNull)
{
if (parms.Length != 0)
throw new ArgumentException("RuleType.NotNull requires 0 parameters", "parms");
ValidationRule = new NotNullValidation();
}
if (type == RuleType.StringMinLength)
{
if (parms.Length != 1)
throw new ArgumentException("RuleType.StringMinLength requires 1 parameter", "parms");
if (!(parms[0] is int))
throw new ArgumentException("RuleType.StringMinLength requires an integer", "parms");
ValidationRule = new StringLengthValidation((int)parms[0]);
}
}
}
The biggest problem with it is that it won't complain until you try to instantiate a class at run-time that has a bad Validation attribute. Your code can run quite happily up until the point where it tries to create an instance of that bad class, at which point all of the attributes will actually be constructed and those ArgumentExceptions start flying.
In fact only the first option doesn't suffer from run-time problems, because you can control the types of parameters being supplied by using the correct constructor formats. You can still tell it to do silly things - like requiring that strings must have less than 0 length for instance - but that's up to you :P

Dynamically load class for rules engine

I have a XML file that defines a lot of rules.
I load the XML file into my rules engine.
Depending on what XML file I load i need to pick which namespace I will find the classes I need. Then on each row of the XML I need to determine what class to load.
My XML
<RuleList assembly="BMW">
<rule>
<code>2345</code>
<errorMessage>foo bar</errorMessage>
<order>1</order>
</rule>
</RuleList>
<RuleList assembly="FORD">
<rule>
<code>0045</code>
<errorMessage>foo bar</errorMessage>
<order>3</order>
</rule>
</RuleList>
I only process one rule list at a time.
Should I be adding an extra XML attribute to each rule defining the ClassName to load?
As I do not want to use the code as the classname? Or can I just add the code as an attribute to my class and use that to load it dynamically
For example
namespace FORD
{
[code=0045]
public bool IsValidColor(foo) : IisValid
{
return true
}
}
Can I load classes from the [code=0045] or should I just stored "IsValidColor" in the XML. Is there a performance difference.
Your attribute syntax doesn't work. But something like [Code("0045")] would, if you create CodeAttribute.
There is going to be some performance difference, because you'll have to find the correct type based on the attribute among all types in the assembly. But the difference is most likely going to be negligible.
To actually do it, define the attribute like this:
[AttributeUsage(AttributeTargets.Class)]
class CodeAttribute : Attribute
{
public CodeAttribute(string code)
{
Code = code;
}
public string Code { get; private set; }
}
And then find the class like this:
var type =
(from t in assembly.GetTypes()
let attr = (CodeAttribute)t
.GetCustomAttributes(typeof(CodeAttribute), false)
.SingleOrDefault()
where attr != null && attr.Code == code
select t)
.Single();
Either option would have similar performance. If the error codes, error messages, and order will never vary across XML files, you could even have all of the metadata about a rule inside of an attribute instead, and at runtime enumerate through all classes that implement IisValid:
[Rule(Code = "0045", ErrorMessage = "foo bar", Order = 1)]
public class IsValidColor : IisValid
{
public bool IsValid(Foo bar)
{
// validation rules here
}
}
However, if all of this is customizable, I'd personally go with having the XML file specify the names of the classes to use.

Retrieving static members of multiple classes programmatically

I am not sure the best approach to this problem, be it through reflection, redesigning my classes altogether, or doing something simple.
Basically I have a base class, and I can have any number of subclasses which inherit from it. Let's call the base class Shape and the subclasses CircleShape, RectangleShape, etc.
The base class is never itself instantiated, only the subclasses. Some are never instatiated, some are instantiated many times throughout the life of the program.
Sometimes I need information specific to a subclass before I instantiate it. Right now I use an enum to differentiate all subclass types. And I instantiate each subclass based on the enum in a switch statement, like this:
switch (shapeType)
{
case CircleShape:
shape = new CircleShape();
case SquareShape:
shape = new RectangleShape();
}
But say instead of having to use this kind of hardcoded switch statement, I wanted to enumerate through all the subclasses. Is there a way to automatically retrieve a list of subclasses and access their STATIC members for info about them (before instantiating them)? Or is it easier to manually instantiate each class once and add them to an array so an I enumerate through them (but not tie those instances to any actual data).
Or should I do something completely different?
You can use attributes to define metadata on your classes and then use reflection to read this metadata at runtime to decide what you want to do with this class without having to instantiate it.
Here's some information on using attributes (you can create your own custom attributes too) using attributes in C#
Here's a quick sample of what this would look like:
Class Defenition:
// ********* assign the attributes to the class ********
[BugFixAttribute(121,"Jesse Liberty","01/03/05")]
[BugFixAttribute(107,"Jesse Liberty","01/04/05", Comment="Fixed off by one errors")]
public class MyMath
{
...
Using Reflection to read the attributes:
// get the member information and use it to retrieve the custom attributes
System.Reflection.MemberInfo inf = typeof(MyMath);
object[] attributes;
attributes = inf.GetCustomAttributes(typeof(BugFixAttribute), false);
// iterate through the attributes, retrieving the properties
foreach(Object attribute in attributes)
{
BugFixAttribute bfa = (BugFixAttribute) attribute;
Console.WriteLine("\nBugID: {0}", bfa.BugID);
Console.WriteLine("Programmer: {0}", bfa.Programmer);
Console.WriteLine("Date: {0}", bfa.Date);
Console.WriteLine("Comment: {0}", bfa.Comment);
}
NOTE: Be careful with using reflection too heavily on large numbers of iterations of large number of objects though, since it comes with a significant performance cost.
You could use reflection to enumerate all your classes, but this is not a very efficient way to do things since it is kind of slow.
If they are all in the same assembly you could do something like:
class Shape
{
/* ... */
}
class CircleShape : Shape
{
public static string Name
{
get
{
return "Circle";
}
}
}
class RectangleShape : Shape
{
public static string Name
{
get
{
return "Rectangle";
}
}
}
class Program
{
static void Main(string[] args)
{
var subclasses = Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(Shape)));
foreach (var subclass in subclasses)
{
var nameProperty = subclass.GetProperty("Name", BindingFlags.Public | BindingFlags.Static);
if (nameProperty != null)
{
Console.WriteLine("Type {0} has name {1}.", subclass.Name, nameProperty.GetValue(null, null));
}
}
}
}
Of course you could also use attributes instead of static members which would probably preferable if you want to decorate the classes with information that you wanted to look up at runtime. There are many examples of how attributes work around the internet.

How can I access an internal class from an external assembly?

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.

Categories