I'm having some trouble understanding your question, but let me attempt to clarify.
I have an object with multiple attributes
...
it will erase all CustomAttributes
In C# parlance, class members of the format <access> <type> <name> { get; set; }
are referred to as "properties" rather than "attributes." "Attributes," on the other hand, are the C# implementation of annotations, such as the custom attributes to which you are referring.
That said, I currently understand you to mean you have an automatically generated class with multiple properties. You would like each of these properties to have their own custom attributes, but if you edit the class they are removed the next time it is generated, and you cannot get the class generator to include custom attributes.
It might be helpful to know more of the context of your class. How is it being generated, for example? If it is an Entity Framework class, the following SO question may provide some insight:
Add data annotations to a class generated by entity framework. In general, is (or can you make) the generated class partial
? If so, then you can still follow the approach in the above question's answer, viz. make your own partial class implementation that provides the properties' custom attributes.
For example, if your generated class looks (or can be made to look) like this:
/// <auto-generated />
public partial class MyClass
{
public int Num1 { get; set; }
public int Num2 { get; set; }
public string Str1 { get; set; }
public string Str2 { get; set; }
}
You could write the other part of the partial class with the custom annotations, like this:
/// human generated
public partial class MyClass
{
[Submit]
public int Num1 { get; set; }
[Submit]
public int Num2 { get; set; }
[Submit]
public string Str1 { get; set; }
[Submit]
public string Str2 { get; set; }
}
Again, without knowing more about your situation, I am not certain if this provides you the information you need, but I hope it at least gives you a starting point.
Edit
If the class is not partial, you might consider wrapping your generated class with a class whose wrapping properties use the custom attribute. For example,
/// human generated
public class MyClassWrapper
{
private readonly MyClass wrapped;
public MyClassWrapper(MyClass wrapped)
{
this.wrapped = wrapped;
}
[Submit]
public int Num1 { get => this.wrapped.Num1; set => this.wrapped.Num1 = value; }
[Submit]
public int Num2 { get => this.wrapped.Num2; set => this.wrapped.Num2 = value; }
[Submit]
public string Str1 { get => this.wrapped.Str1; set => this.wrapped.Str1 = value; }
[Submit]
public string Str2 { get => this.wrapped.Str2; set => this.wrapped.Str2 = value; }
}
Edit 2
If you would rather have a more dynamic solution, at the cost of some design and runtime complexity, you might consider this SO question: How to add property-level Attribute to the TypeDescriptor at runtime?. It seems to address a similar concern --
Really, it's for MS's Application Settings that generates code, so you can't extend it in any way property-wise.
I won't duplicate Gman's explanation entirely here, but essentially this approach consists of
- Get the type (
MyClass
) or an instance of the type myObject
- Use
TypeDescriptor.GetProvider(MyClass
/myObject).GetTypeDescriptor(MyClass
/myObject)
to get the type or object's baseline ICustomTypeDescriptor
- Construct his
PropertyOverridingTypeDescriptor
with this baseline descriptor
- Iterate through
MyClass
/myObject
's properties' definitions with TypeDescriptor.GetProperties(MyClass
/myObject)
. Use TypeDescriptor.CreateProperty
to create a new property definition based on the current property's definition, that adds the custom attribute EditorAttribute
(or in your case SubmitAttribute
), and use the PropertyOverridingTypeDescriptor
constructed in 3. to use the new property definition.
- Construct his
TypeDescriptorOverridingProvider
with the PropertyOverridingTypeDescriptor
constructed in 3.
- Apply the new property definitions to
MyClass
/myObject
with TypeDescriptor.AddProvider