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
Related
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?
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)]
I am using Json.Net for serialization and unserialization on a class. When I try to obsfucate the class in an assembly, I will not be able to unserialize the JSON string correctly. I have try using JsonProperty Attribute but it still not able to unserialize correctly.
Does anyone know how to get around this other than setting the class not to obsfucate?
Thanks in advance.
Updates:
I have created a simple class for JSON object as below:
public class JsonTestClass
{
[JsonProperty("JsonID")]
public int Id { get; set; }
[JsonProperty("JsonName")]
public string Name { get; set; }
[JsonProperty("JsonYesNo")]
public bool YesNo { get; set; }
}
And the code to serialize JsonTestClass objects into Json string is:
//Serialize
var jsonObj = new JsonTestClass()
{
Id = 1,
Name = "John",
YesNo = true,
};
var JsonStr = JsonConvert.SerializeObject(jsonObj);
Trace.WriteLine(">>" + JsonStr);
And unserialize Json string to JsonTestClass is as follow:
//Unserialize
var JsonStr = "{\"JsonID\":1,\"JsonName\":\"John Abc\",\"JsonYesNo\":true}";
Trace.WriteLine("<<" + JsonStr);
var jsonObj = JsonConvert.DeserializeObject<JsonTestClass>(JsonStr);
if (jsonObj == null)
{
Trace.WriteLine("-- JsonObj is null");
}
else
{
Trace.WriteLine(string.Format("-- Id={0} Name={1} YesNo={2}", jsonObj.Id, jsonObj.Name, jsonObj.YesNo));
}
Everything works fine unobsfucated and the debug output for serialization is:
[64200] >>{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true}
And debug output for deserialization is:
[64200] <<{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true}
[64200] -- Id=1 Name=John Abc YesNo=True
After the assembly has been obsfucated (using SmartAssembly to obsfucate this) and using dotPeek to see the obsfucated assembly, the only one which somewhat resemble the JsonTestClass are:
namespace
{
internal class
{
}
}
The debug output for serialization is:
[65956] >>{}
The debug output for deserialization is:
[65956] <<{"JsonID":1,"JsonName":"John Abc","JsonYesNo":true}
[65956] -- Id=0 Name= YesNo=False
Hope this helps to clear things up.
If you are using Dotfuscator which is shipped as Community Edition with Visual Studio 15 and Visual Studio 17, you have to exclude the property names of the object you serialize from renaming. You do this in the Dotfuscator renaming tab.
After that you can serialize and deserialize like normal.
You find a detailed description here in the support corner of the Preemtive Solutions web site.
There are a couple of options, depending on your preference as to maintainability, security, etc.
Excluding properties from obfuscation
If it's just the type names that you're concerned about being obfuscated and not the property names, then you can decorate each property that is to be serialized with the Obfuscation attribute. (Here is the link for Dotfuscator's support for this attribute.) Basically, by excluding the property from renaming, this will allow Json.NET to easily identify the properties to set.
[Obfuscation(Exclude=true, Feature="renaming")]
public int MyProperty { get; set; }
Pros: Easy and straightforward
Cons: You lose some security by not
obfuscating your property names.
Expose the private backing field for deserialization
Another way to get Json.NET to deserialize an obfuscated class is to change the target of the deserialization from the public property to the private field using the JsonProperty attribute, e.g.
[JsonProperty("a")]
private int _myField;
[JsonIgnore]
public int MyProperty
{
get => _myField;
set => _myField = value;
}
NOTE: If you use "MyProperty" or nameof(MyProperty) in the JsonProperty attribute, then depending on your obfuscation settings it's very possible that it will be compiled into the .dll as "MyProperty", thus reducing the overall security that you were trying to achieve with obfuscation in the first place.
NOTE 2: This solution will most likely not work when working with the MVVM design pattern. When using this pattern, a common coding practice is to utilize the property setter to raise the INotifyPropertyChanged event. However, using the JsonProperty and JsonIgnore attributes will cause Json.NET to set the value directly on the private field using reflection instead of the via the property setter. Therefore the change event will not be raised, making this a poor solution in this particular scenario.
Pros: You can maintain full obfuscation of your property names.
Cons: You need to create backing fields for every obfuscated property that you want to participate in serialization/deserialization. Also, may break the INotifyPropertyChanged functionality when using with the MVVM pattern, depending on your implementation details.
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..
I have the following class definition:
public class CallGroupViewModel
{
public string Name { get; set; }
public string BulkEmails { get; set; }
public List<dynamic> Members {get;set;}
}
The Members property is some dynamic knockout code and the contents change depending on UI stuff. I am wanting to take a short cut since the UI is so up in the air right now.
My problem is that when it get to my action method, everything gets populate, including Members but its a array of objects and I can't get at the individual properties on them.
public ActionResult SaveGroup(CallGroupViewModel group)
group.Members //this has a count
group.Members[0].email //this pukes as 'email' is not valid for 'object'
I'm probably just missing something, any help is appreciated.
Thanks!
The model binding system which populates MVC action method arguments isn't intended to work with dynamic objects. The system requires type information to know which information to bind. Consider changing your model to use strong types instead.
For accessing dynamic properties from the object, in your case you can use :
var email = group.Members[0].GetType()
.GetProperty("Email")
.GetValue(group.Members[0], null);