Im haveing some xml that have this structure
<Person Id="*****" Name="*****">
<AccessControlEntries>
<AccessControlEntry Id="*****" Name="****"/>
</AccessControlEntries>
<AccessControls />
<IdentityGroups>
<IdentityGroup Id="****" Name="*****" />
</IdentityGroups></Person>
and i also have this entities
[DataContract(IsReference = true)]
public abstract class EntityBase
{
protected bool serializing;
[DataMember(Order = 1)]
[XmlAttribute()]
public string Id { get; set; }
[DataMember(Order = 2)]
[XmlAttribute()]
public string Name { get; set; }
[OnDeserializing()]
public void OnDeserializing(StreamingContext context)
{
this.Initialize();
}
[OnSerializing()]
public void OnSerializing(StreamingContext context)
{
this.serializing = true;
}
[OnSerialized()]
public void OnSerialized(StreamingContext context)
{
this.serializing = false;
}
public abstract void Initialize();
public string ToXml()
{
var settings = new System.Xml.XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
var sb = new System.Text.StringBuilder();
using (var writer = System.Xml.XmlWriter.Create(sb, settings))
{
var serializer = new XmlSerializer(this.GetType());
serializer.Serialize(writer, this);
}
return sb.ToString();
}
}
[DataContract()]
public abstract class Identity : EntityBase
{
private EntitySet<AccessControlEntry> accessControlEntries;
private EntitySet<IdentityGroup> identityGroups;
public Identity()
{
Initialize();
}
[DataMember(Order = 3, EmitDefaultValue = false)]
[Association(Name = "AccessControlEntries")]
public EntitySet<AccessControlEntry> AccessControlEntries
{
get
{
if ((this.serializing && (this.accessControlEntries==null || this.accessControlEntries.HasLoadedOrAssignedValues == false)))
{
return null;
}
return accessControlEntries;
}
set
{
accessControlEntries.Assign(value);
}
}
[DataMember(Order = 4, EmitDefaultValue = false)]
[Association(Name = "IdentityGroups")]
public EntitySet<IdentityGroup> IdentityGroups
{
get
{
if ((this.serializing && (this.identityGroups == null || this.identityGroups.HasLoadedOrAssignedValues == false)))
{
return null;
}
return identityGroups;
}
set
{
identityGroups.Assign(value);
}
}
private void attach_accessControlEntry(AccessControlEntry entity)
{
entity.Identities.Add(this);
}
private void dettach_accessControlEntry(AccessControlEntry entity)
{
entity.Identities.Remove(this);
}
private void attach_IdentityGroup(IdentityGroup entity)
{
entity.MemberIdentites.Add(this);
}
private void dettach_IdentityGroup(IdentityGroup entity)
{
entity.MemberIdentites.Add(this);
}
public override void Initialize()
{
this.accessControlEntries = new EntitySet<AccessControlEntry>(
new Action<AccessControlEntry>(this.attach_accessControlEntry),
new Action<AccessControlEntry>(this.dettach_accessControlEntry));
this.identityGroups = new EntitySet<IdentityGroup>(
new Action<IdentityGroup>(this.attach_IdentityGroup),
new Action<IdentityGroup>(this.dettach_IdentityGroup));
}
}
[XmlType(TypeName = "AccessControlEntry")]
public class AccessControlEntry : EntityBase, INotifyPropertyChanged
{
private EntitySet<Service> services;
private EntitySet<Identity> identities;
private EntitySet<Permission> permissions;
public AccessControlEntry()
{
services = new EntitySet<Service>(new Action<Service>(attach_Service), new Action<Service>(dettach_Service));
identities = new EntitySet<Identity>(new Action<Identity>(attach_Identity), new Action<Identity>(dettach_Identity));
permissions = new EntitySet<Permission>(new Action<Permission>(attach_Permission), new Action<Permission>(dettach_Permission));
}
[DataMember(Order = 3, EmitDefaultValue = false)]
public EntitySet<Permission> Permissions
{
get {
if ((this.serializing && (this.permissions.HasLoadedOrAssignedValues == false)))
{
return null;
}
return permissions;
}
set
{
permissions.Assign(value);
}
}
[DataMember(Order = 4, EmitDefaultValue = false)]
public EntitySet<Identity> Identities
{
get
{
if ((this.serializing && (this.identities.HasLoadedOrAssignedValues == false)))
{
return null;
}
return identities;
}
set
{
identities.Assign(identities);
}
}
[DataMember(Order = 5, EmitDefaultValue = false)]
public EntitySet<Service> Services
{
get
{
if ((this.serializing && (this.services.HasLoadedOrAssignedValues == false)))
{
return null;
}
return services;
}
set
{
services.Assign(value);
}
}
private void attach_Permission(Permission entity)
{
entity.AccessControlEntires.Add(this);
}
private void dettach_Permission(Permission entity)
{
entity.AccessControlEntires.Remove(this);
}
private void attach_Identity(Identity entity)
{
entity.AccessControlEntries.Add(this);
}
private void dettach_Identity(Identity entity)
{
entity.AccessControlEntries.Remove(this);
}
private void attach_Service(Service entity)
{
entity.AccessControlEntries.Add(this);
}
private void dettach_Service(Service entity)
{
entity.AccessControlEntries.Remove(this);
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
#endregion
public override void Initialize()
{
throw new NotImplementedException();
}
}
[DataContract()]
[XmlType(TypeName = "Person")]
public class Person : Identity
{
private EntityRef<Login> login;
[DataMember(Order = 3)]
[XmlAttribute()]
public string Nombre { get; set; }
[DataMember(Order = 4)]
[XmlAttribute()]
public string Apellidos { get; set; }
[DataMember(Order = 5)]
public Login Login {
get
{
return login.Entity;
}
set
{
var previousValue = this.login.Entity;
if (((previousValue != value) || (this.login.HasLoadedOrAssignedValue == false)))
{
if ((previousValue != null))
{
this.login.Entity = null;
previousValue.Person = null;
}
this.login.Entity = value;
if ((value != null))
value.Person = this;
}
}
}
public override void Initialize()
{
base.Initialize();
}
}
[DataContract()]
[XmlType(TypeName = "Login")]
public class Login : EntityBase
{
private EntityRef<Person> person;
[DataMember(Order = 3)]
public string UserID { get; set; }
[DataMember(Order = 4)]
public string Contrasena { get; set; }
[DataMember(Order = 5)]
public Domain Dominio
{
get;
set;
}
public Person Person
{
get
{
return person.Entity;
}
set
{
var previousValue = this.person.Entity;
if (((previousValue != value) || (this.person.HasLoadedOrAssignedValue == false)))
{
if ((previousValue != null))
{
this.person.Entity = null;
previousValue.Login = null;
}
this.person.Entity = value;
if ((value != null))
value.Login = this;
}
}
}
public override void Initialize()
{
throw new NotImplementedException();
}
}
[DataContract()]
[XmlType(TypeName = "IdentityGroup")]
public class IdentityGroup : Identity
{
private EntitySet<Identity> memberIdentities;
public IdentityGroup()
{
Initialize();
}
public override void Initialize()
{
this.memberIdentities = new EntitySet<Identity>(new Action<Identity>(this.attach_Identity), new Action<Identity>(this.dettach_Identity));
}
[DataMember(Order = 3, EmitDefaultValue = false)]
[Association(Name = "MemberIdentities")]
public EntitySet<Identity> MemberIdentites
{
get
{
if ((this.serializing && (this.memberIdentities.HasLoadedOrAssignedValues == false)))
{
return null;
}
return memberIdentities;
}
set
{
memberIdentities.Assign(value);
}
}
private void attach_Identity(Identity entity)
{
entity.IdentityGroups.Add(this);
}
private void dettach_Identity(Identity entity)
{
entity.IdentityGroups.Remove(this);
}
}
[DataContract()]
[XmlType(TypeName = "Group")]
public class Group : Identity
{
public override void Initialize()
{
throw new NotImplementedException();
}
}
but the ToXml() response something like this
<Person xmlns:xsi="************" xmlns:xsd="******" ID="******" Name="*****"/><AccessControlEntries/></Person>
but what i want is something like this
<Person Id="****" Name="***" Nombre="****">
<AccessControlEntries/>
<IdentityGroups/>
</Person>
Try using the following Serialize method:
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
serializer.Serialize(writer, this, ns);
Related
When user update the property Curso (type Curso), this update does not work in Entity Framework. All data in object of type Turma are updated, but property Curso. Follow bellow my code:
This is the data received by PUT method in MVC controller:
{
"Id":1,
"DataVencimento":"2017-11-24T00:00:00",
"Nome":".Net MVCss",
"Turno":"Tarde",
"Curso":
{
"Id":1,
"Nome":"teste",
"Duracao":2,
"ValorAnuidade":5888.88,
"QtdParcelas":2,
"ValorParcela":22.22,
"ValorMatricula":22.22,
"Disciplinas":null,
"CorpoDocente":null,
"Documentos":null,
"Turmas":null
}
}
This is PUT method in MVC Controller:
[HttpPut]
public HttpResponseMessage Update(TurmaDto dto)
{
var response = new HttpResponseMessage();
IKernel ninjectKernel = new StandardKernel();
ninjectKernel.Bind<ITurmaBLO>().To<TurmaBLO>();
ITurmaBLO blo = ninjectKernel.Get<ITurmaBLO>();
Turma t = Mapper.Map<TurmaDto, Turma>(dto);
if (!blo.Update(t))
{
response = Request.CreateResponse(HttpStatusCode.NotFound, "Turma não encontrada.");
}
else
{
response = Request.CreateResponse(HttpStatusCode.OK, t);
}
return response;
}
This is Class TurmaBLO:
public class TurmaBLO : GenericaBLO<Turma>, ITurmaBLO
{
private IKernel ninjectKernel = new StandardKernel();
private ITurmaDAO _dao;
public TurmaBLO()
{
ninjectKernel.Bind<ITurmaDAO>().To<TurmaDAO>();
_dao = ninjectKernel.Get<ITurmaDAO>();
}
public override bool Add(Turma e)
{
return _dao.Add(e);
}
public override bool Update(Turma e)
{
return _dao.Update(e);
}
public override List<Turma> GetAll()
{
return _dao.GetAll();
}
public override Turma Get(int id)
{
return _dao.Get(id);
}
}
This is Class GenericaBLO:
public class GenericaBLO<T> : IGenericaBLO<T> where T : class
{
public GenericaDAO<T> dao;
public virtual bool Add(T e)
{
dao = new GenericaDAO<T>();
return dao.Add(e);
}
public virtual bool Update(T e)
{
dao = new GenericaDAO<T>();
return dao.Update(e);
}
public virtual bool Delete(T e)
{
dao = new GenericaDAO<T>();
return dao.Delete(e);
}
public virtual List<T> GetAll()
{
dao = new GenericaDAO<T>();
return dao.GetAll();
}
public virtual T Get(int id)
{
dao = new GenericaDAO<T>();
return dao.Get(id);
}
public void ValidateForAdd()
{
throw new NotImplementedException();
}
public void ValidateForUpdate()
{
throw new NotImplementedException();
}
public void ValidateForDelete()
{
throw new NotImplementedException();
}
}
This is Class TurmaDAO:
internal class TurmaDAO : GenericaDAO<Turma>, ITurmaDAO
{
public override bool Add(Turma e)
{
base.Context.Curso.Attach(e.Curso);
return base.Add(e);
}
public override bool Update(Turma e)
{
base.Context.Curso.Attach(e.Curso);
return base.Update(e);
}
public override List<Turma> GetAll()
{
return base.Context.Turma.Include(c => c.Curso).Include(dt => dt.Descontos).ToList();
}
public override Turma Get(int id)
{
return base.Context.Turma.Include(c => c.Curso).Include(dt => dt.Descontos).SingleOrDefault(c => c.Id == id);
}
}
This is Class GenericaDAO:
public class GenericaDAO<T> : IGenericaDAO<T> where T : class
{
internal ApplicationDbContext Context { get; set; }
protected DbSet<T> DbSet { get; set; }
public GenericaDAO()
{
Context = new ApplicationDbContext();
DbSet = Context.Set<T>();
}
public virtual bool Add(T e)
{
try
{
Context.Entry(e).State = EntityState.Added;
Context.SaveChanges();
return true;
}
catch (Exception ex)
{
return false;
}
}
public virtual bool Update(T e)
{
try
{
Context.Entry(e).State = EntityState.Modified;
Context.SaveChanges();
return true;
}
catch (Exception ex)
{
return false;
}
}
public virtual bool Delete(T e)
{
try
{
Context.Entry(e).State = EntityState.Deleted;
Context.SaveChanges();
return true;
}
catch (Exception ex)
{
return false;
}
}
public virtual List<T> GetAll()
{
return DbSet.ToList();
}
public virtual T Get(int id)
{
return DbSet.Find(id);
}
}
This is Class TurmaDto:
public class TurmaDto
{
public int Id { get; set; }
public DateTime DataVencimento { get; set; }
public string Nome { get; set; }
public string Turno { get; set; }
public CursoDto Curso { get; set; }
}
This is Class Turma:
public class Turma
{
public int Id { get; set; }
public DateTime DataVencimento { get; set; }
public string Nome { get; set; }
public string Turno { get; set; }
public Curso Curso { get; set; }
}
You also need to call Update on the child entities, in your case Curso. So:
ITurmaBLO bloT = ninjectKernel.Get<ITurmaBLO>();
ICursoBLO blo = ninjectKernel.Get<ICursoBLO>();
Turma t = Mapper.Map<TurmaDto, Turma>(dto);
if(!(bloT.Update(t) && bloC.Update(t.Curso))){
response = Request.CreateResponse(HttpStatusCode.NotFound, "Turma não encontrada.");
}
If you need to only update the relation from Turma to Curso without changing the Curso, it's enough to set Turma.CursoId to the Id of the new Curso, assuming the relationship is mapped correctly in EF.
I have three projects :
App.Models: Contains object interfaces.
App.WebAPIService: RESTFul API service using JSON.
App.Client: WPF application that communicates with RESTful API Service.
I use Entity Framework to create interfaces and models.
App.Models is used in the other two projects to create objects.
public interface ISheet
{
int ID { get; set; }
string Name { get; set; }
Nullable<System.DateTime> CreatedDate { get; set; }
string CreatedUser { get; set; }
ICollection<ICategory> Category { get; set; }
}
public interface ICategory
{
int ID { get; set; }
string Name { get; set; }
}
App.WebAPIService:
[DataContract(IsReference = true)]
[KnownType(typeof(Category))]
public partial class Sheet : ISheet
{
#region Primitive Properties
[DataMember]
public int ID
{
get;
set;
}
[DataMember]
public Nullable<System.DateTime> CreatedDate
{
get;
set;
}
[DataMember]
public string CreatedUser
{
get;
set;
}
[DataMember]
public string Name
{
get;
set;
}
#endregion
#region Navigation Properties
[DataMember]
public ICollection<ICategory> Category
{
get
{
if (_category == null)
{
var newCollection = new FixupCollection<ICategory>();
newCollection.CollectionChanged += FixupCategory;
_category = newCollection;
}
return _category;
}
set
{
if (!ReferenceEquals(_category, value))
{
var previousValue = _category as FixupCollection<ICategory>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupCategory;
}
_category = value;
var newValue = value as FixupCollection<ICategory>;
if (newValue != null)
{
newValue.CollectionChanged += FixupCategory;
}
}
}
}
private ICollection<ICategory> _category;
#endregion
#region Association Fixup
private void FixupCategory(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (ICategory item in e.NewItems)
{
if (!item.Sheet.Contains(this))
{
item.Sheet.Add(this);
}
}
}
if (e.OldItems != null)
{
foreach (ICategory item in e.OldItems)
{
if (item.Sheet.Contains(this))
{
item.Sheet.Remove(this);
}
}
}
}
#endregion
}
public class SheetController : ApiController
{
private TORDBEntities db = new TORDBEntities();
/// <summary>
/// GET api/Sheet/5
/// </summary>
/// <param name="id">int</param>
/// <returns>Sheet</returns>
public Sheet GetSheet(int id)
{
Sheet sheet = db.Sheet.Include("Category").Single(s => s.ID == id);
if (sheet == null)
{
throw new HttpResponseException
(Request.CreateResponse(HttpStatusCode.NotFound));
}
return sheet;
}
}
App.Client:
public class Sheet : ISheet
{
public int ID { get; set; }
public DateTime? CreatedDate { get; set; }
public string CreatedUser { get; set; }
public string Name { get; set; }
public ICollection<ICategory> Category { get; set; }
}
class ServiceSheet
{
public Sheet sheet = new Sheet();
public Sheet GetSheet(int id)
{
string url = ConfigurationManager.AppSettings["UrlWebService"];
url += #"api/sheet/" + id;
HttpWebRequest requete = WebRequest.Create(url) as HttpWebRequest;
requete.Method = WebRequestMethods.Http.Get;
requete.BeginGetResponse(new AsyncCallback(this.GetSheetResponseCallback),
requete);
return sheet;
}
private void GetSheetResponseCallback(IAsyncResult ar)
{
//Récupération de l'objet HttpWebRequest
HttpWebRequest requete = (HttpWebRequest)ar.AsyncState;
try
{
using (HttpWebResponse reponse = requete.EndGetResponse(ar)
as HttpWebResponse)
{
using (StreamReader streamReader = new
StreamReader(reponse.GetResponseStream()))
{
string Text = streamReader.ReadToEnd();
sheet = JsonConvert.DeserializeObject<Sheet>(Text);
//Newtonsoft.Json.JsonSerializer serializer = new
Newtonsoft.Json.JsonSerializer();
//serializer.Converters.Add(new DTOJsonConverter());
//Sheet maSheet = serializer.Deserialize(streamReader);
}
}
}
catch (WebException we)
{
if (we.Status == WebExceptionStatus.ProtocolError)
{
HttpWebResponse r = (HttpWebResponse)we.Response;
if (r.StatusCode == HttpStatusCode.NotFound)
MessageBox.Show("Code d'erreur: " + r.StatusCode.ToString());
r.Close();
}
else
MessageBox.Show(we.Message + " " + we.Status.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Erreur");
}
}
}
I get an error for deserialization category. I have tried the following:
public class Sheet : ISheet
{
public int ID { get; set; }
public DateTime? CreatedDate { get; set; }
public string CreatedUser { get; set; }
public string Name { get; set; }
[JsonConverter(typeof(ConcreteTypeConverter<Category>))]
public ICollection<ICategory> Category { get; set; }
}
public class ConcreteTypeConverter<TConcrete> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
//assume we can convert to anything for now
return true;
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
//explicitly specify the concrete type we want to create
return serializer.Deserialize<TConcrete>(reader);
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
//use the default serialization - it works fine
serializer.Serialize(writer, value);
}
}
Error:
Unable to cast object of type 'System.Collections.Generic.List1[App.Client.Models.Category]' to
type 'System.Collections.Generic.ICollection1[App.Models.ICategory]'.
And this:
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
//explicitly specify the concrete type we want to create
List<TConcrete> liste = serializer.Deserialize<List<TConcrete>>(reader);
ICollection<TConcrete> coll = new Collection<TConcrete>();
liste.ForEach(delegate(TConcrete obj)
{
coll.Add(obj);
});
return coll;
}
Error:
Unable to cast object of type
'System.Collections.Generic.Collection1[App.Client.Models.Category]'
to type
'System.Collections.Generic.ICollection1[App.Models.ICategory]'.
I think the problem is just ICollection; have you ever encountered this problem, or do you have a better solution?
Answer :
OK, it's my fault !
I forgotten to add this part of code client side :
public class Sheet : ISheet
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<ICategory> Category
{
get
{
if (_category == null)
{
var newCollection = new FixupCollection<ICategory>();
newCollection.CollectionChanged += FixupCategory;
_category = newCollection;
}
return _category;
}
set
{
if (!ReferenceEquals(_category, value))
{
var previousValue = _category as FixupCollection<ICategory>;
if (previousValue != null)
{
previousValue.CollectionChanged -= FixupCategory;
}
_category = value;
var newValue = value as FixupCollection<ICategory>;
if (newValue != null)
{
newValue.CollectionChanged += FixupCategory;
}
}
}
}
private ICollection<ICategory> _category;
private void FixupCategory(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (ICategory item in e.NewItems)
{
if (!item.Sheet.Contains(this))
{
item.Sheet.Add(this);
}
}
}
if (e.OldItems != null)
{
foreach (ICategory item in e.OldItems)
{
if (item.Sheet.Contains(this))
{
item.Sheet.Remove(this);
}
}
}
}
}
public class FixupCollection<T> : ObservableCollection<T>
{
protected override void ClearItems()
{
new List<T>(this).ForEach(t => Remove(t));
}
protected override void InsertItem(int index, T item)
{
if (!this.Contains(item))
{
base.InsertItem(index, item);
}
}
}
Without FixupCategory, it couldn't work.
Hope, this will help some people.
Thanks to those who helped me.
I have some trouble when I try to map object to int.
My classes and method where convert:
[Serializable]
public class ProfileProperty
{
public object PropertyValue { get; set; }
public bool IsVisible { get; set; }
public ProfileProperty(object value, bool isVisible = true)
{
this.PropertyValue = value;
this.IsVisible = isVisible;
}
public ProfileProperty()
{
this.IsVisible = true;
}
public T GetValue<T>()
{
return (T)this.PropertyValue;
}
public override string ToString()
{
if (this.PropertyValue != null)
{
return this.PropertyValue.ToString();
}
return string.Empty;
}
}
[Serializable]
public class ProfileProperty
{
public object PropertyValue { get; set; }
public bool IsVisible { get; set; }
public ProfileProperty(object value, bool isVisible = true)
{
this.PropertyValue = value;
this.IsVisible = isVisible;
}
public ProfileProperty()
{
this.IsVisible = true;
}
public T GetValue<T>()
{
return (T)this.PropertyValue;
}
public override string ToString()
{
if (this.PropertyValue != null)
{
return this.PropertyValue.ToString();
}
return string.Empty;
}
}
public static class Helper
{
public static ProfileModel PopulProfMod(Profile profile)
{
var mapper = ObjectMapperManager.DefaultInstance.GetMapper<Profile, ProfileModel>(new DefaultMapConfig()
.IgnoreMembers<Profile, ProfileModel>(new string[] { "GetValue", "ToString" }));
ProfileModel prof = new ProfileModel();
if (profile != null)
{
prof = mapper.Map(profile);
//prof.Age = (int)profile.Age.PropertyValue;
prof.Visibility = new List<string>();
}
//Some code
return prof;
}
}
When mapped property Age is 0 but profile:
Profile profile = new Profile()
{
Age = new ProfileProperty() { IsVisible = true, PropertyValue = 17 },
Comments = 2,
UserName = "Luck",
FirstName = new ProfileProperty() { IsVisible = false, PropertyValue = "Alex" }
};
You need a converter:
new DefaultMapConfig()
.IgnoreMembers<Profile, ProfileModel>(new string[] { "GetValue", "ToString" }))
.ConvertUsing<ProfileProperty, int>(s => (int)s.PropertyValue)
public class OrderXml
{
public enum DeliveryType { FTP, Email, HDD, Tape, Aspera, MLT };
public class Order
{
public int UserId { get; private set; }
public int OrderBinId { get; private set; }
public int TenantId { get; private set; }
public Delivery Delivery { get; set; }
public Recipient Recipient { get; private set; }
public string[] AssetDmGuids { get; set; }
public Order(int orderBinId, string[] assetDmGuids, DeliveryType type, int recipientId, string recipientName)
{
Delivery = new Delivery(type);
Recipient = new Recipient(recipientId, recipientName);
// UserId = SessionHelper.Instance.GetUserId();
// TenantId = SessionHelper.Instance.GetTenantID().ToString();
OrderBinId = orderBinId;
AssetDmGuids = assetDmGuids;
}
public void GetXml()
{
}
}
public class Recipient
{
int _id;
string _name = string.Empty;
public Recipient(int id, string name)
{
this._id = id;
this._name = name;
}
public int Id { get { return _id; } }
public string Name { get { return _name; } }
}
public class Delivery
{
DeliveryType _deliveryType;
string _ftpLocation = string.Empty;
string _ftpPath = string.Empty;
string[] _emailAddresses;
string _deliveryAddress = string.Empty;
string _deliveryComments = string.Empty;
string _asperaLocation = string.Empty;
public string FtpPath
{
get { return _ftpPath; }
set { _ftpPath = value; }
}
public string[] EmailAddresses
{
get { return _emailAddresses; }
set { _emailAddresses = value; }
}
public string DeliveryAddress
{
get { return _deliveryAddress; }
set { _deliveryAddress = value; }
}
public string DeliveryComments
{
get { return _deliveryComments; }
set { _deliveryComments = value; }
}
public string AsperaLocation
{
get { return _asperaLocation; }
set { _asperaLocation = value; }
}
public string FtpLocation
{
get { return _ftpLocation; }
set { _ftpLocation = value; }
}
public Delivery(DeliveryType type)
{
_deliveryType = type;
}
}
public static void Main()
{
Order ord = new Order(1, new string[] { "123", "124", "125" }, DeliveryType.Tape, 1, "vh1");
}
}
public XmlDocument GetXml()
{
XmlDocument retValue = new XmlDocument();
try
{
XmlSerializer xs = new XmlSerializer(this.GetType());
Stream stream = new MemoryStream();
xs.Serialize( stream, toSerialize );
stream.Position = 0;
retValue.Load( stream );
}
catch (Exception ex)
{
}
return retValue;
}
This is a variation of Marc Gravels's answer
I'd extent Marc Gravels's helpful example to view nested objects in a generic way. But System throws an System.Reflection.TargetException.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
public class Author
{
public string LastName { get; set; }
public string FirstName { get; set; }
}
public class BookDetails
{
public string Title { get; set; }
public int TotalRating { get; set; }
public int Occurrence { get; set; }
public Author Author { get; set; }
}
//public class MyBindingSource<T> : BindingSource
class MyList<T> : List<T>, ITypedList
{
public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
var origProps = TypeDescriptor.GetProperties(typeof(T));
List<PropertyDescriptor> newProps = new List<PropertyDescriptor>(origProps.Count);
foreach (PropertyDescriptor prop in origProps)
{
var childProps = TypeDescriptor.GetProperties(prop.GetType());
if ((childProps.Count == 0) || isSimpleType(prop))
{
newProps.Add(prop);
}
else
{
foreach (PropertyDescriptor childProp in childProps)
{
newProps.Add(new MyPropertyDescriptor(prop, childProp));
}
}
}
return new PropertyDescriptorCollection(newProps.ToArray());
}
private static bool isSimpleType(PropertyDescriptor prop)
{
if (prop.PropertyType.BaseType == typeof(ValueType)) return true;
if (prop.PropertyType == typeof(string)) return true;
if (prop.PropertyType.BaseType != typeof(Object)) return true;
return false;
}
public string GetListName(PropertyDescriptor[] listAccessors)
{
return "";
}
}
class MyPropertyDescriptor : PropertyDescriptor
{
private static readonly Attribute[] nix = new Attribute[0];
private readonly PropertyDescriptor parent;
private readonly PropertyDescriptor child;
public MyPropertyDescriptor(PropertyDescriptor parent, PropertyDescriptor child)
: base(parent.Name + "." + child.Name, nix)
{
this.parent = parent;
this.child = child;
}
public override object GetValue(object component)
{
return child.GetValue(component);
}
public override Type PropertyType
{
get { return child.PropertyType; }
}
public override bool IsReadOnly
{
get { return true; }
}
public override void SetValue(object component, object value)
{
throw new NotSupportedException();
}
public override void ResetValue(object component)
{
throw new NotSupportedException();
}
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return parent.ComponentType; }
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
var author1 = new Author() { FirstName = "Victor", LastName = "Hugo" };
var author2 = new Author() { FirstName = "Moore", LastName = "Thomas" };
var data = new MyList<BookDetails> {
new BookDetails { Title = "abc", TotalRating = 3, Occurrence = 2, Author = author1 },
new BookDetails { Title = "def", TotalRating = 3, Occurrence = 2, Author = author2 },
new BookDetails { Title = "ghi", TotalRating = 3, Occurrence = 2, Author = author1 },
new BookDetails { Title = "jkl", TotalRating = 3, Occurrence = 2, Author = author2 },
};
Application.Run(new Form
{
Controls = {
new DataGridView {
Dock = DockStyle.Fill,
DataSource = data
}
}
});
}
}
You should Change prop.GetType() to prop.PropertyType.
I found the solution by myself:
The error was in the MyPropertyDescriptor!
Correction:
class MyPropertyDescriptor : PropertyDescriptor
{
private static readonly Attribute[] nix = new Attribute[0];
private readonly PropertyDescriptor parent;
private readonly PropertyDescriptor child;
public MyPropertyDescriptor(PropertyDescriptor parent, PropertyDescriptor child)
: base(parent.Name + "." + child.Name, nix)
{
this.parent = parent;
this.child = child;
}
public override object GetValue(object component)
{
var temp = parent.GetValue(component);
if (temp == null) return null;
var temp2 = child.GetValue(temp);
return temp2;
}
public override Type PropertyType
{
get { return child.PropertyType; }
}
public override bool IsReadOnly
{
get { return true; }
}
public override void SetValue(object component, object value)
{
throw new NotSupportedException();
}
public override void ResetValue(object component)
{
throw new NotSupportedException();
}
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return parent.ComponentType; }
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}