wcf вопрос новичка: массивы как свойства - PullRequest
4 голосов
/ 21 июня 2011

У меня есть класс DataContract, который имеет свойство типа List<AnotherObject>. Другой объект также помечается с помощью DataContract. По какой-то причине это свойство взято из службы wcf как null, хотя я заполняю его на сервере. Это по замыслу?

Вот, пожалуйста. Определения классов:

[DataContract]
    public class UserInfo
    {
        [DataMember]
        public decimal UserID
        {
            get;
            protected internal set;
        }

        [DataMember]
        public string UserName
        {
            get;
            protected internal set;
        }

        [DataMember]
        public string Pswd
        {
            get;
            protected internal set;
        }       

        [DataMember]
        public List<decimal> RoleID
        {
            get;
            protected internal set;
        }

        List<UserRole> userRolesTable = new List<UserRole>();
        [DataMember]
        public List<UserRole> UserRoles
        {
            get
            {
                return userRolesTable;
            }
            protected internal set { }
        }       
    }



[DataContract]
    public class UserRole
    {
        [DataMember]
        public decimal ROLEID { get; internal set; }

        [DataMember]
        public string ROLE_CODE { get; internal set; }

        [DataMember]
        public string ROLE_DESCRIPTION { get; internal set; }

        [DataMember]
        public decimal FORMID { get; internal set; }

        [DataMember]
        public string FORMCODE { get; internal set; }

        [DataMember]
        public string FORMNAME { get; internal set; }
    }

Свойство UserRoles имеет значение null.

Ответы [ 5 ]

3 голосов
/ 21 июня 2011

Почему вы разрешаете автоматически реализовывать свойство RoleId, но не UserRoles?Код как есть не будет работать, потому что у вас есть пустой установщик.Вам, вероятно, следует просто использовать для этого авто-свойство:

[DataMember]
public List<UserRole> UserRoles
{
    get; set;
}      

Или, по крайней мере, предоставить содержательный установщик.Установщик ничего не делает, поэтому десериализатор не может заполнить значение.

1 голос
/ 21 июня 2011
List<UserRole> userRolesTable = new List<UserRole>();
[DataMember]
public List<UserRole> UserRoles
{
    get
    {
        return userRolesTable;
    }
    protected internal set { }
} 

Ваш сеттер пуст.Поместите несколько

userRolesTable = value;

Другое дело, ваши свойства DataContract должны иметь public setters.

1 голос
/ 21 июня 2011

Ваш Setter в свойстве UserRoles установлен как внутренний. Поскольку инфраструктура WCF будет задавать свойство, оно прекращает присваивать значение, поскольку оно указано как внутреннее.

http://connect.microsoft.com/data/feedback/details/625985/wcf-client-entities-with-internal-setters-and-internalsvisibletoattribute-on-asmbly-fail

Вы можете сделать то, что предлагает эта ссылка, используя атрибут InternalsVisibleToAttribute для этого свойства, но я никогда не использовал его.

обновление Я пытаюсь сказать, что я уверен, что сериализация работает нормально, платформа WCF не может вставить десериализованное значение в код хоста, поскольку на основании контракта с данными внутренняя секция Setter свойства недоступна. используйте атрибут InternalVisibleTo, чтобы сообщить платформе сериализации WCF доступ к установщику клиентской версии вашего объекта контракта данных.

0 голосов
/ 21 июня 2011

По сути, это проблема сериализации.Я имел эту проблему в моем коде в прошлом, но это было какое-то время, так что терпите меня.

Во-первых, мы должны выяснить, являются ли объектные отношения нулевыми, перед вызовом WCF, поэтому поставьтеотладка до и после.

Если объект возвращается как нулевой до вызова, у вас есть несколько вариантов:

  1. Вы можете явно использовать .Include ("AnotherObject") в вашем DbContext, чтобы получить объект.Я использовал это, когда мой метод Read взял массив строк, которые я использовал для включения всех необходимых объектов.Это идеальнее, чем автоматическое получение всех объектов, потому что во время сериализации, если вы берете все, вы можете легко завершить сериализацию всей базы данных, что, помимо прочего, приводит к проблемам с производительностью и безопасностью.

  2. Другой вариант - использовать динамический прокси, добавив ключевое слово virtual перед вашим списком.Однако DataContractSerializer имеет проблему с сериализацией динамических прокси, поэтому вам нужно реализовать атрибут, который использует ProxyDataContractResolver вместо DataContractResolver.Этот атрибут должен применяться ко всем OperationContracts, которые могут передавать динамический прокси.Это автоматически примет ВСЕ ссылки на объекты, что, вероятно, является плохой практикой кодирования, поэтому я рекомендую описанный выше метод.

    public class ApplyDataContractResolverAttribute : Attribute, IOperationBehavior
    {
    
      public ApplyDataContractResolverAttribute() { }
    
      public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters) { }
    
      public void ApplyClientBehavior(OperationDescription description, System.ServiceModel.Dispatcher.ClientOperation proxy)
      {
        DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
      }
    
      public void ApplyDispatchBehavior(OperationDescription description, System.ServiceModel.Dispatcher.DispatchOperation dispatch)
      {
        DataContractSerializerOperationBehavior dataContractSerializerOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        dataContractSerializerOperationBehavior.DataContractResolver = new ProxyDataContractResolver();
      }
    
      public void Validate(OperationDescription description) { }
    
    }
    

Редактировать: Также я думаю, что вы можете иметь сеттеры в контрактах данныхне быть публичным, потому что я делаю это, и это прекрасно работает :).Но я бы попытался сначала сделать ваш установщик открытым, затем решить проблему, а затем вернуться к защищенному установщику, чтобы вы имели дело с как можно меньшим количеством переменных за раз.

0 голосов
/ 21 июня 2011

Вам нужно реализовать сеттер ...

protected internal set { userRolesTable = value; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...