Common Compiler Infrastructure: How to work with ICustomAttribute - c#

I'm attempting to use CCI-Metadata for creating a code generator, by iterating over a set of assemblies, discovering the types and their metadata and then generating the code. I would like to be able to control the code generation by attaching custom attributes to the metadata of the original types.
Something like:
[GenerateSpecialClass(true, "foo", IsReallySpecial=false)]
public class MyClass { ... }
I have a INamedTypeDefinition and get an IEnumerable from the Attributes property. From here, I can't figure out what to do to get the value of custom attribute and it's properties.
Could someone give me a code sample: given an ICustomAttribute, how I can retrieve the values from my example attribute. Assume it's definition is:
public GenericSpecialClassAttribute : Attribute
{
public bool Prop1 { get; set; }
public string Prop2 {get; set; }
public bool IsReallySpecial {get; set; }
public GenericSpecialClassAttribute(bool prop1, string prop2)
{
Prop1 = prop1;
Prop2 = prop2;
}
}
Any help would be very much appreciated. I assume I cast this to some other interface and do something magical on it; but I couldn't find a helper that did anything with it and don't fully understand the implementation/model hierarchy.

Try casting to Microsoft.Cci::IMetadataConstant. Here's a sample code that dumps data out of Microsoft.Cci::ICustomAttribute.
public static void parseCustomAttribute(Cci::ICustomAttribute customAttribute)
{
foreach (Cci::IMetadataNamedArgument namedArg in customAttribute.NamedArguments)
{
parseNamedArgument(namedArg);
}
foreach (Cci::IMetadataExpression arg in customAttribute.Arguments)
{
parseFixedArgument(arg);
}
Console.WriteLine("Type Reference:\t\t"+ customAttribute.Type.ToString());
var constructor = customAttribute.Constructor as Cci::IMethodDefinition;
if (constructor != null)
{
//parseMethodDefinition(constructor);
}
else
{
//parseMethodReference(constructor);
}
}
private static void parseFixedArgument(Cci::IMetadataExpression fixedArgument)
{
Console.WriteLine("Type Reference:\t\t" + fixedArgument.Type.ToString());
var constValue = fixedArgument as Cci::IMetadataConstant;
if (constValue != null)
{
Console.WriteLine("Value :" + constValue.Value);
}
}
private static void parseNamedArgument(Cci::IMetadataNamedArgument namedArg)
{
Console.WriteLine("Name:" + "\t\t" + namedArg.ArgumentName.Value);
parseFixedArgument(namedArg.ArgumentValue);
}
IMetadataNamedArgument refers to name/value pairs in the Value blob stream in metadata. They are used to specify fields and properties. For your class, CCI makes IsReallySpecial available as an IMetadataNamedArgument
IMetadataExpression refers to argument values of the constructor. So args prop1 and prop2 are kept as MetadataExpression in CCI object model.

Check out Jason Bock's Injectors. I think he does what you are looking for in his InjectorContext.Find() method and then the looks up the different properties/parameters in the NotNullInjector.OnInject() method.
Get his code up and running, then you'll have a better understanding of how to do what you're looking to do.

Related

Property never null c#

When refactoring code, I come up with instances like the following
private string _property = string.Empty;
public string Property
{
set { _property = value ?? string.Empty); }
}
Later on in a method I see the following:
if (_property != null)
{
//...
}
Assuming that _property is only set by the setter of Property, is this code redundant?
I.e is there any way, through reflection wizardry or other methods that _property can ever be null?
Assuming that _property is only set by the setter of Property, is this
code redundant?
Exactly, it is redundant. This is the actual purpose of Properties. We shouldn't access the fields of a class directly. We should access them using a Property. So in the corresponding setter, we can embed any logic and we can rest assure that each time we try to set a value this logic would be verified once more.This argument holds even for the methods of a class. In a method we must use the properties and not the actual fields. Furthermore, when we want to read the value of a field, we should make use of the corresponding getter.
In general, properties enhances the concept of encapsulation, which is one of the pillars of object oriented programming OOP.
Many times there isn't any logic that should be applied when we want to set a value. Take for instance the following example:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
We have declared a class for representing a Customer. A Customer object should have three properties an Id, a FirstName and a LastName.
An immediate question, when someones read this class is why should someone make use of properties here?
The answer is again the same, they provide a mechanism of encapsulation. But let's consider how can this help us in the long run. Let's say that one day someone decides that the first name of a customer should be a string of length less than 20. If the above class had been declared as below:
public class Customer
{
public int Id;
public string FirstName;
public string LastName;
}
then we should check for the length of FirstName in each instance we had created ! Otherwise, if we had picked the declaration with the properties, we could just easily make use of Data Annotations
public class Customer
{
public int Id { get; set; }
[StringLength(20)]
public string FirstName { get; set; }
public string LastName { get; set; }
}
and that's it. Another approach it could be the following:
public class Customer
{
public int Id { get; set; }
private string firstName;
public string FirstName
{
get { return firstName }
set
{
if(value!=null && value.length<20)
{
firstName = value;
}
else
{
throw new ArgumentException("The first name must have at maxium 20 characters", "value");
}
}
}
public string LastName { get; set; }
}
Consider both of the above approaches with having to revisit all your codebase and make this check. It's crystal clear that properties win.
Yes, it is possible through reflection. Nevertheless, I wouldn't worry about reflection -- people using reflection to defeat the design of your class is not something I worry about.
There is, however, something I do worry about: the phrase "Assuming that _property is only set by the setter of Property" is key. You are preventing users of your class from setting property to null.
You do not prevent, however, yourself or some other maintainer of your class from forgetting to only use the property INSIDE your class. In fact, your example has some one checking the field from inside the class rather than the property itself.... which means that, within your class, access comes from both the field and the property.
In most cases (where the problem could only come from inside the class) I would use an assertion and assert the field is not null.
If I really, really, really wanted to make sure that it wasn't null (barring reflection or people hell-bent on breaking things), you could try something like this:
internal class Program
{
static void Main()
{
string example = "Spencer the Cat";
UsesNeverNull neverNullUser = new UsesNeverNull(example);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = null;
Debug.Assert(neverNullUser.TheString != null);
Console.WriteLine(neverNullUser.TheString);
neverNullUser.TheString = "Maximus the Bird";
Console.WriteLine(neverNullUser.TheString);
}
}
public class UsesNeverNull
{
public string TheString
{
get { return _stringValue.Value; }
set { _stringValue.Value = value; }
}
public UsesNeverNull(string s)
{
TheString = s;
}
private readonly NeverNull<string> _stringValue = new NeverNull<string>(string.Empty, str => str ?? string.Empty);
}
public class NeverNull<T> where T : class
{
public NeverNull(T initialValue, Func<T, T> nullProtector)
{
if (nullProtector == null)
{
var ex = new ArgumentNullException(nameof(nullProtector));
throw ex;
}
_value = nullProtector(initialValue);
_nullProtector = nullProtector;
}
public T Value
{
get { return _nullProtector(_value); }
set { _value = _nullProtector(value); }
}
private T _value;
private readonly Func<T, T> _nullProtector;
}
It is basically redundant. However, if it were mission critical or if for some reason it caused terrible side effects, it could remain. It is hard to tell, but part of your question was "can reflection change this value to null" to which the answer is yes and can be seen here in this linqpad demo
void Main()
{
var test = new Test();
test.Property = "5";
Console.WriteLine(test.Property);//5
FieldInfo fieldInfo = test.GetType().GetField("_property",BindingFlags.NonPublic | BindingFlags.Instance);
fieldInfo.SetValue(test, null);
Console.WriteLine(test.Property);//null
}
public class Test
{
private string _property = string.Empty;
public string Property
{
get { return _property; }
set { _property = value ?? string.Empty; }
}
}
I know this question is old, but look, I needed that one of my string properties never came up in null.
So I did this, and It worked for me
public string Operation { get; set; } = string.Empty;
In this way the default value is a string empty, but never null.

Object with some fix properties and some dynamic properties serialization

I have one class that contains some fixed properties, and along with that I also have to support a dynamic property which is decided at run time.
My problem is that I want to serialize that class to json, so I decided to inherit from Dictionary.
public class TestClass : Dictionary<string,object>
{
public string StudentName { get; set; }
public string StudentCity { get; set; }
}
And I am using it like this:
static void Main(string[] args)
{
TestClass test = new TestClass();
test.StudentCity = "World";
test.StudentName = "Hello";
test.Add("OtherProp", "Value1");
string data = JsonConvert.SerializeObject(test);
Console.WriteLine(data);
Console.ReadLine();
}
My output is like this:
{"OtherProp":"Value1"}
but I expected this:
{"OtherProp":"Value1", "StudentName":"Hello" , "StudentCity":"World"}
As you can see, it does not serialize StudentName and StudentCity.
I know that one solution is to add Fix property to dictionary using Reflection or use Json.net it self JObject.FromObject but to do this I have to do manipulation.
I also tried to decorate TestClass with the JObject attribute, but it does not produce the desired output.
I don't want to write a custom converter for this as this would be my last option.
Any help or suggestion would be highly appreciated.
You clould implement your class like this
public class TestClass : Dictionary<string, object>
{
public string StudentName
{
get { return this["StudentName"] as string; }
set { this["StudentName"] = value; }
}
public string StudentCity
{
get { return this["StudentCity"] as string; }
set { this["StudentCity"] = value; }
}
}
That way those fixed properties will actually be like helpers for easy access.
Notice the way I am setting the value in the dictionary. That way if the key do not exists it will be created and the value assigned to that key otherwise the value will be updated.

Best way to create instance of child object from parent object

I'm creating a child object from a parent object. So the scenario is that I have an object and a child object which adds a distance property for scenarios where I want to search. I've chosen to use inheritance as my UI works equivalently with either a search object or a list of objects not the result of a location search. So in this case inheritance seems a sensible choice.
As present I need to generate a new object MyObjectSearch from an instance of MyObject. At present I'm doing this in the constructor manually by setting properties one by one. I could use reflection but this would be slow. Is there a better way of achieving this kind of object enhancement?
Hopefully my code below illustrates the scenario.
public class MyObject {
// Some properties and a location.
}
public class MyObjectSearch : MyObject {
public double Distance { get; set; }
public MyObjectSearch(MyObject obj) {
base.Prop1 = obj.Prop1;
base.Prop2 = obj.Prop2;
}
}
And my search function:
public List<MyObjectSearch> DoSearch(Location loc) {
var myObjectSearchList = new List<MyObjectSearch>();
foreach (var object in myObjectList) {
var distance = getDistance();
var myObjectSearch = new MyObjectSearch(object);
myObjectSearch.Distance = distance;
myObjectSearchList.add(myObjectSearch);
}
return myObjectSearchList;
}
The base class needs to define a copy constructor:
public class MyObject
{
protected MyObject(MyObject other)
{
this.Prop1=other.Prop1;
this.Prop2=other.Prop2;
}
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class MyObjectSearch : MyObject
{
public double Distance { get; set; }
public MyObjectSearch(MyObject obj)
: base(obj)
{
this.Distance=0;
}
public MyObjectSearch(MyObjectSearch other)
: base(other)
{
this.Distance=other.Distance;
}
}
This way the setting of properties is handled for all derived classes by the base class.
You can use reflection to copy properties.
public class ChildClass : ParentClass
{
public ChildClass(ParentClass ch)
{
foreach (var prop in ch.GetType().GetProperties())
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(ch, null), null);
}
}
}
There is no easy way to do this, unfortunately. As you said, you would either have to use reflection, or create a "Clone" method that would generate a new child object using a parent object as input, like so:
public class MyObjectSearch : MyObject {
// Other code
public static MyObjectSearch CloneFromMyObject(MyObject obj)
{
var newObj = new MyObjectSearch();
// Copy properties here
obj.Prop1 = newObj.Prop1;
return newObj;
}
}
No matter what, you're either going to end up writing reflection code (which is slow), or writing each property out by hand. It all depends on whether or not you want maintainability (reflection) or speed (manual property copy).
A generic solution would be to serialize it to json and back. In the json-string is no information about the class name from which it was serialized.
Most people do this in javascript.
As you see it works well for pocco objects but i don't guarantee that it works in every complex case. But it does event for not-inherited classes when the properties are matched.
using Newtonsoft.Json;
namespace CastParentToChild
{
public class Program
{
public static void Main(string[] args)
{
var p = new parent();
p.a=111;
var s = JsonConvert.SerializeObject(p);
var c1 = JsonConvert.DeserializeObject<child1>(s);
var c2 = JsonConvert.DeserializeObject<child2>(s);
var foreigner = JsonConvert.DeserializeObject<NoFamily>(s);
bool allWorks = p.a == c1.a && p.a == c2.a && p.a == foreigner.a;
//Your code goes here
Console.WriteLine("Is convertable: "+allWorks + c2.b);
}
}
public class parent{
public int a;
}
public class child1 : parent{
public int b=12345;
}
public class child2 : child1{
}
public class NoFamily{
public int a;
public int b = 99999;
}
// Is not Deserializeable because
// Error 'NoFamily2' does not contain a definition for 'a' and no extension method 'a' accepting a first argument of type 'NoFamily2' could be found (are you missing a using directive or an assembly reference?)
public class NoFamily2{
public int b;
}
}
If a shallow copy is enough, you can use the MemberwiseClone method.
Example:
MyObject shallowClone = (MyObject)original.MemberwiseClone();
If you need a deep copy, you can serialize/deserialize like this: https://stackoverflow.com/a/78612/1105687
An example (assuming you write an extension method as suggested in that answer, and you call it DeepClone)
MyObject deepClone = original.DeepClone();
I first came accros this question when I was looking for doing this.
If you are able to work with C# 9 and record-classes. You only have to create a new constructor in the sub-class taking in a base class object and hand it over to the subclass:
public record MyObject {
...
}
public record MyObjectSearch :MyObject
{
public MyObjectSearch(MyObject parent) : base(parent) { }
...
}
Then you can create the child object like this:
MyObject parent = new();
MyObjectSearch m = new MyObjectSearch(parentObj) { Distance = 1.1};
Credits to https://stackoverflow.com/a/64573044/2582968
Seems natural for the base object to have constructor with parameters for its properties:
public class MyObject
{
public MyObject(prop1, prop2, ...)
{
this.Prop1 = prop1;
this.Prop2 = prop2;
}
}
So then, in your descendant object you can have:
public MyObjectSearch(MyObject obj)
:base(obj.Prop1, obj.Prop2)
This reduces duplication related to assignments. You could use reflection to automatically copy all properties, but this way seems more readable.
Note also, that if your classes have so much properties that you're thinking about automatizing of copying of the properties, then they are likely to violate the Single Responsibility Principle, and you should rather consider changing your design.
There are libraries to handle this; but if you just want a quick implementation in a few places, I would definitely go for a "copy constructor" as previously suggested.
One interesting point not mentioned is that if an object is a subclass, then it can access the child's private variables from the within the parent!
So, on the parent add a CloneIntoChild method. In my example:
Order is the parent class
OrderSnapshot is the child class
_bestPrice is a non-readonly private member on Order. But Order can set it for OrderSnapshot.
Example:
public OrderSnapshot CloneIntoChild()
{
OrderSnapshot sn = new OrderSnapshot()
{
_bestPrice = this._bestPrice,
_closed = this._closed,
_opened = this._opened,
_state = this._state
};
return sn;
}
NOTE: Readonly member variables MUST be set in the constructor, so you will have to use the child constructor to set these...
Although I don't like "up-sizing" generally, I use this approach a lot for analytic snapshots...

How to refer to a property of a class (not an object)?

I have a module that iterates through the public properties of an object (using Type.GetProperties()), and performs various operations on these properties. However, sometimes some of the properties should be handled differently, e.g., ignored. For example, suppose I have the following class:
class TestClass
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
Now, I would like to be able to specify that whenever my module gets an object of type TestClass, the property Prop2 should be ignored. Ideally I would like to be able to say something like this:
ReflectionIterator.AddToIgnoreList(TestClass::Prop2);
but that obviously doesn't work. I know I can get a PropertyInfo object if I first make an instance of the class, but it doesn't seem right to create an artificial instance just to do this. Is there any other way I can get a PropertyInfo-object for TestClass::Prop2?
(For the record, my current solution uses string literals, which are then compared with each property iterated through, like this:
ReflectionIterator.AddToIgnoreList("NamespaceName.TestClass.Prop2");
and then when iterating over the properties:
foreach (var propinfo in obj.GetProperties())
{
if (ignoredProperties.Contains(obj.GetType().FullName + "." + propinfo.Name))
// Ignore
// ...
}
but this solution seems a bit messy and error-prone...)
List<PropertyInfo> ignoredList = ...
ignoredList.Add(typeof(TestClass).GetProperty("Prop2"));
should do the job... just check whether ignoredList.Contains(propinfo)
Could you add attributes to the properties to define how they should be used? eg
class TestClass
{
public int Prop1 { get; set; }
[Ignore]
public int Prop2 { get; set; }
}

How do I get the value of the used parameters in a constructor (C#)

I've got a question about getting the values from a constructor in a generic way.
namespace myTestNamespace
{
Public Class myTestClass()
{
Public myTestClass(int myInt,bool myBool, double myDouble)
{
//do / set something
}
Public myTestClass(int myInt,bool myBool)
{
//do / set something
}
}
}
Using (what you need);
Using myTestNamespace;
namespace MyIWannaLookForTheParametersName
{
Public Class MyLookUpClass()
{
Public void DoSomething()
{
List<object> myList = new List<object>();
myTestClass _ myTestClass = new myTestClass(1,true,2.5);
object mySaveObject = myTestClass;
mylist.Add(mySaveObject);
//how do I get the info from the right constructor
//(I used the one with 3 parameters_
//what was the value of myInt, myBool and myDouble
//how can I make it generic enough, so it will work with other classes with
// different constructors ass well?
}
}
}
Questions about intent aside, there's no generic way for you to do this. Information about what methods have been called and what values were supplied is not saved automatically. You are, of course, perfectly able to keep track of these things yourself, but you would have to write each class to do this explicitly.
Doing this in a generic way is asking for trouble. What if I did this?
public class Foo
{
public string Name { get; set; }
}
public class Bar
{
public Bar(Foo foo)
{
// ...
}
}
Then suppose I called it in this way:
Foo f = new Foo();
f.Name = "Jim";
Bar b = new Bar(f);
f.Name = "Bob";
Now, if such a generic system existed, what would be the value of foo for the Bar constructor? Either it reports "Bob" (which is what the value for Name is on the instance of Foo that was supplied), or it reports "Jim", meaning that the runtime or library would essentially have to be smart enough to make a deep copy of the object so that the state is not changed.
The bottom line is this: if you need access to the parameters passed to the constructor (or any other function), you'll have to store them somewhere explicitly.
You can't get thevalues from the constructor. You need to first place them in a property or a field within your class. The example you provided is a poor use of generics. You wouldbe better off placing the constructor values into properties and creating an interface with those properties.
I got what I needed with this method:
private static ParameterSettings[] GetListOfParametersFromIndicator(object indicatorClass, int loopId, myEnums.ParaOrResult paraOrResult)
{
return (from prop in indicatorClass.GetType().GetProperties()
let loopID = loopId
let Indicator = indicatorClass.GetType().Name
let value = (object)prop.GetValue(indicatorClass, null)
where prop.Name.Contains("_Constr_")
select new ParameterSettings { ParaOrResult=paraOrResult, LoopID= loopId, Indicator= Indicator, ParaName= prop.Name, Value= value }).ToArray();
}
where ParameterSettings is:
public struct ParameterSettings
{
public myEnums.ParaOrResult ParaOrResult { get; set; }
public int LoopID { get; set; }
public string Indicator { get; set; }
public string ParaName { get; set; }
public object Value { get; set; }
}
This info is ok for me. Thanks for the replies.
Regards,
Matthijs

Categories

Resources