.NET How to change class atribute in runtime? - c#

I've got an issue with changing attribute at runtime.
I'm using https://www.filehelpers.net/ to handle csv but I think this problem is similar for any other custom attributes.
There is a class representing entity:
[DelimitedRecord("\t")]
public class FileHelper
{
[FieldNotEmpty]
public string Id = "1";
public string Name = "Product1"
}
This class is used as generic parameter for file reading engine. What I want to do is to change DelimitedRecord("\t") to a runtime value eg. semicolon .
I know that I can use below code to get attributes but only read.
DelimitedRecordAttribute[] attributes = (DelimitedRecordAttribute[]) typeof(FileHelper).GetCustomAttributes(typeof(DelimitedRecordAttribute), false);
Is there option to change attribute value or remove it and add new attribute new value?

Related

Why does openapi-generator create InlineObjects?

I'm using
https://github.com/OpenAPITools/openapi-generator
to create a client for my API. It's mostly working ok, but the generator creates a lot of InlineObject types that encapsulate parameters that include types of any complexity, e.g Dictionary, IFormFile, Stream
For example,
public async Task<ApiResponse<FileUploadResponseAPIModel>> MyApiClientMethod(InlineObject11 inlineObject11 = default(InlineObject11))
{
}
Where InlineObject11 is defined as
public partial class InlineObject11 : IEquatable<InlineObject11>, IValidatableObject
{
[JsonConstructorAttribute]
protected InlineObject11() { }
public InlineObject11(Stream rebalanceTradeFile = default(Stream))
{
// to ensure "rebalanceTradeFile" is required (not null)
this.RebalanceTradeFile = rebalanceTradeFile ?? throw new ArgumentNullException("rebalanceTradeFile is a required property for InlineObject11 and cannot be null");
}
[DataMember(Name = "RebalanceTradeFile", IsRequired = true, EmitDefaultValue = false)]
public System.IO.Stream RebalanceTradeFile { get; set; }
What is the point of this? Why isn't the client generated to take Stream rebalanceTradeFile instead of wrapping it into an InlineObject? How can I fix it? This is breaking a bunch of my tools that use older versions of the generated client.
Inline Object is created from inline schema, e.g. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/test/resources/3_0/inline_model_resolver.yaml#L15-L24 is a schema with 2 properties defined inline for the payload with the MIME type application/json.
To avoid OpenAPI Generator automatically generating a model for the inline schema, one can define the model separately (example) and use $ref instead:
application/json:
schema:
$ref: '#/components/schemas/Pet'
Using title field in schema object, the model name is title name instead of InlineObject.

Ignoring / Not Mapping certain POCO properties in NEST 2.0

I am having a hard time finding good detail on NEST 2.0, the wrapper for Elasticsearch 2.2 I am using. My question is this: Can I do a bulk insert on an object (class with public data members) and map that to Elasticsearch where only the mapped fields between my C# class and the ES server mapping will save? And it will not add the additional fields in my class I do not want?
Right now I have a class of with strings and doubles and lists of other classes in it. I want to save the strings and doubles, but NOT include the Lists on my bulk inserts to Elasticsearch. It wants to save every piece of data in every field of my class. Is there a class member attribute or some other way to say "do not add this field if it has no mapping" that I have missed? I hope so.
You can ignore properties of your POCO in a number of ways with NEST 2.x. Let's use the following POCO as an example
using Nest;
using Newtonsoft.Json;
[ElasticsearchType(Name = "company")]
public class Company
{
public string Name { get; set; }
[String(Ignore = true)]
public string IgnoreViaAttribute { get; set; }
public string IgnoreViaSettings { get;set; }
[JsonIgnore]
public string IgnoreViaSerializerSpecificAttribute { get; set; }
}
1.Using the Ignore property on a derived ElasticsearchPropertyAttribute type (in our example, StringAttribute on IgnoreViaAttribute property) applied to the property that should be ignored on the POCO
2.Using the .InferMappingFor<TDocument>(Func<ClrTypeMappingDescriptor<TDocument>, IClrTypeMapping<TDocument>> selector) on the connection settings
var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
.InferMappingFor<Company>(i => i
.Ignore(p => p.IgnoreViaSettings)
);
var client = new ElasticClient(settings);
These settings are cached per instance of ConnectionSettings.
3.Using an ignore attribute applied to the POCO property that is understood by the IElasticsearchSerializer used, and inspected inside of the CreatePropertyMapping() on the serializer. In the case of the default JsonNetSerializer, this is the Json.NET JsonIgnoreAttribute. In our example, this is demonstrated by the attribute applied to the IgnoreViaSerializerSpecificAttribute property.
What I found by digging around a bit and testing a small class is that the following structure did indeed hide the attributes when you post a class with NEST 2.0 C#. If you do this just above the class member you wish to ignore when doing a bulk add that covers it.
[String(Ignore = true)]

Sitecore SearchResulItem - fluent API?

In Sitecore, how can I define index field names on derived SearchResultItem class' properties other than [IndexField] attribute?
I'm trying to use the same interfaces I use for Glass.Mapper model definitions, and it already contains [SitecoreField] attribute on properties which define the Sitecore field name (and therefore the index field name).
Thank you!
I would check out this project:
https://github.com/cardinal252/Lucinq.Sitecore
It links Glass.Mapper and the Lucene index.
Mike
I don't think thats possible, since 'IndexField' and 'SitecoreField' represent different things, 'IndexField' attribute sets the name of the index field, for example, 'IndexField("_id")', 'IndexField("_language")' represent the id and language fields names inside lucene document.
Now, Sitecore by default, store the index names of all fields by it's name in Sitecore, for example, a field called 'Content' will be stored inside lucene document as 'content' by default. which you can change to something else if you want.
SitecoreField attribute represent the actual name of a field for an item, so that glass can map that field value into the property.
Bottom line, you just need to specify IndexField and SitecoreField on each property in your class, since each attribute works differently
I believe you could change Sitecore Glass Mapper SitecoreFieldAttribute to accomplish that.
You could implement the interface IIndexFieldNameFormatterAttribute on the Glass MapperSitecoreFieldAttribute.
This interface you will find in the Sitecore.ContentSearch.Linq.dll and it looks like that:
namespace Sitecore.ContentSearch
{
public interface IIndexFieldNameFormatterAttribute : _Attribute
{
string GetIndexFieldName(string fieldName);
string GetTypeFieldName(string fieldName);
}
}
Your implementation would be that, I pasted only the interface methods here.
namespace Glass.Sitecore.Mapper.Configuration.Attributes
{
/// <summary>
/// Used to populate the property with data from a Sitecore field
/// </summary>
public class SitecoreFieldAttribute: AbstractSitecorePropertyAttribute, IIndexFieldNameFormatterAttribute
{
public string GetIndexFieldName(string fieldName)
{
return this.FieldName;
}
public string GetTypeFieldName(string fieldName)
{
return fieldName;
}
I haven`t test it, but as I could see Sitecore Linq rely on this interface to find the fields names. You can investigate it yourself, but here is the piece of code which made me deduce that:
var variable = (from p in (IEnumerable<PropertyInfo>)typeof(TItem).GetProperties()
select new { Property = p, Attribute = (IIndexFieldNameFormatterAttribute)p.GetCustomAttributes().FirstOrDefault<Attribute>((Attribute a) => a is IIndexFieldNameFormatterAttribute) }).FirstOrDefault((p) => p.Attribute != null);
if (variable != null && variable.Attribute.GetIndexFieldName(variable.Property.Name) == this.FieldName)
{
property = variable.Property;
}
Hope it helps..

How to define an alias for a property

I want to generate aliases for properties in generated code. All I could do so far was:
partial class Purchase
{
public User Customer
{
get
{
return this.User;
}
set
{
this.User = value;
}
}
}
I wonder if there is any other way to define an alias in C#. The Purchase class was generated by Linq-to-SQL
In the case that you want a different name of property to send information to JSON using newtonSoft, you can use
[JsonProperty("alias_name")]
public type YourProperty {get;set;}
This can help you if you don't want that your object follow the C# convention and match with the JSON object to be received or sent
No, it's not possible to do in C#. Property name is single identifier you can define for it.
Don't know if this is what you're searching for or not:
but you can define (say) a Dictionary<string,object> where Key is a propertyname and value is a value of the property. In this way you can define dynamic property cash, with changing property names and values at runtime.
or can use an ExpandoObject , if you use C# 4.0

How to retrieve the value of a Custom Attribute from a DLL Loaded at runtime?

I have a app that requires a dll to be loaded at runtime and I want to create some Custom Attributes in the dynamically loaded DLL so when it is loaded I can check to make sure that certain attributes have certain values before trying to use it.
I create an attribute like this
using System;
[AttributeUsage(AttributeTargets.Class)]
public class ValidReleaseToApp : Attribute
{
private string ReleaseToApplication;
public ValidReleaseToApp(string ReleaseToApp)
{
this.ReleaseToApplication = ReleaseToApp;
}
}
In the dynamically loaded DLL I set the attribute like this
[ValidReleaseToApp("TheAppName")]
public class ClassName : IInterfaceName
etc... etc....
But when I try and read the Attribute Value I only get the Attribute Name "ValidReleaseToApp" How do I retrieve the Value "TheAppName"?
Assembly a = Assembly.LoadFrom(PathToDLL);
Type type = a.GetType("Namespace.ClassName", true);
System.Reflection.MemberInfo info = type;
var attributes = info.GetCustomAttributes(true);
MessageBox.Show(attributes[0].ToString());
Update:
Since I am Dynamically loading the dll at runtime the definition of the Attribute is not avail. to the Main App. So when I try to do the following as suggested
string value = ((ValidReleaseToApp)attributes[0]).ReleaseToApplication;
MessageBox.Show(value);
I get this error
The type or namespace name 'ValidReleaseToApp' could not be found
Update2:
OK so the problem was that I defined the Attribute within the project of the dynamically loaded DLL. Once I moved the Attribute definitions to it's own project and Added a reference to that project to both the Main Project and that of the Dynamically loaded dll The suggested code worked.
This should work, I don't have an example in front of me right now, but it looks right. You're basically skipping the steps of exposing the property you want access to, and casting to the attribute type to retrieve that property.
using System;
[AttributeUsage(AttributeTargets.Class)]
public class ValidReleaseToApp : Attribute
{
private string _releaseToApplication;
public string ReleaseToApplication { get { return _releaseToApplication; } }
public ValidReleaseToApp(string ReleaseToApp)
{
this._releaseToApplication = ReleaseToApp;
}
}
Assembly a = Assembly.LoadFrom(PathToDLL);
Type type = a.GetType("Namespace.ClassName", true);
System.Reflection.MemberInfo info = type;
var attributes = info.GetCustomAttributes(true);
if(attributes[0] is ValidReleaseToApp){
string value = ((ValidReleaseToApp)attributes[0]).ReleaseToApplication ;
MessageBox.Show(value);
}
Once you have the custom attributes, you can cast them to instances of the attribute class and access their proerties:
object[] attributes = info.GetCustomAttributes(typeof(ValidReleaseToAppAttribute), true);
ValidReleaseToAppAttrigute attrib = attributes[0] as ValidReleaseToAppAttribute;
MessageBox.Show(attrib.ReleaseToApp);

Categories

Resources