سؤال

أحاول تحديد نوع معروف في التكوين الخاص بي ، لكنني أواجه مشاكل في حقيقة أنه مستمد من الكائن. يمكنني جعلها تعمل في تحديد النوع المعروف عبر السمة. لكن في هذه الحالة ، أحتاج إلى جعلها تعمل من التكوين.

إليك مثال. ما يلي يعمل بشكل جيد:

[ServiceContract]
[ServiceKnownType(typeof(MyData))]
public interface IContract
{
    [OperationContract]
    void Send(object data);
}

[DataContract]
public class MyData
{
    [DataMember]
    public string Message { get; set; }
}

ولكن إذا قمت بإزالة سمة Servicentype ووضع ما يلي في التكوين:

<system.runtime.serialization>
  <dataContractSerializer>
    <declaredTypes>
      <add type="System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <knownType type="WpfApplication1.MyData, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </add>
    </declaredTypes>
  </dataContractSerializer>
</system.runtime.serialization>

أحصل على configurationRrusexception مع رسالة "قيمة" النوع "غير صالحة. الخطأ هو: type system.Object لا يمكن استخدامها كنوع معلن في التكوين."

هل هناك على أي حال لجعل هذا العمل عبر التكوين؟

هل كانت مفيدة؟

المحلول

تبين أن الإجابة لا يمكن القيام بما أريد القيام به في ملف التكوين وحده. يتوافق التكوين أعلاه مع السمة [المعروفة] المستخدمة في DataContracts. يبدو أنه لا توجد طريقة لتنفيذ [servownytype] في التكوين.

تتمثل النهج البديل في استخدام سمة [ServownyType (MethodName ، type)] مع قسم التكوين المخصص. يشبه التكوين الجديد هذا:

<configuration>
  <configSections>
    <section
      name="serviceKnownTypes"
      type="WpfApplication1.ServiceKnownTypesSection, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
  </configSections>
  <serviceKnownTypes>
    <declaredServices>
      <serviceContract type="WpfApplication1.IContract, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <knownTypes>
          <knownType type="WpfApplication1.MyData, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
        </knownTypes>
      </serviceContract>
    </declaredServices>
  </serviceKnownTypes>
</configuration>

العقود:

[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(KnownTypeHelper))]
public interface IContract
{
    [OperationContract]
    void Send(object data);
}

[DataContract]
public class MyData
{
    [DataMember]
    public string Message { get; set; }
}

فئة المساعدة التي تحتوي على رد الاتصال الذي يرجع قائمة الأنواع المعروفة

public static class KnownTypeHelper
{
    public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
    {
        List<Type> result = new List<Type>();

        ServiceKnownTypesSection serviceKnownTypes = (ServiceKnownTypesSection)ConfigurationManager.GetSection("serviceKnownTypes");
        DeclaredServiceElement service = serviceKnownTypes.Services[((Type)(provider)).AssemblyQualifiedName];

        foreach (ServiceKnownTypeElement knownType in service.KnownTypes)
        {
            result.Add(knownType.Type);
        }

        return result;
    }
}

يمكن العثور على معلومات حول إنشاء أقسام تكوين مخصصة هنا:

http://msdn.microsoft.com/en-us/library/2tw134k3.aspx

http://msdn.microsoft.com/en-us/library/system.configuration.configurationCollectionAttribute.aspx

نصائح أخرى

لست متأكدًا مما إذا كان ذلك حسب التصميم ، لكن المعروفة لن يرمي أدناه خطأ إذا لم تعلن عن عقد خدمة مع أنواع معروفة. (أي اختياري لإضافة أنواع معروفة إلى عقود الخدمة).

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;

/// <summary>
/// Helper for finding the known types for Wcf Services from a configuration file.
/// </summary>
public static class KnownTypeHelper
{
    /// <summary>
    /// Gets the known types for the service from a configuration file.
    /// </summary>
    /// <param name="provider">
    /// The provider.
    /// </param>
    /// <returns>
    /// The known types for the service from a configuration file.
    /// </returns>
    public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
    {
        var result = new List<Type>();

        var serviceKnownTypes = (ServiceKnownTypesSection)ConfigurationManager.GetSection("serviceKnownTypes");
        if (serviceKnownTypes != null)
        {
            var service = serviceKnownTypes.Services[((Type)provider).AssemblyQualifiedName];

            if (service != null)
            {
                foreach (ServiceKnownTypeElement knownType in service.KnownTypes)
                {
                    result.Add(knownType.Type);
                }
            }
        }

        return result;
    }
}

لإنقاذ شخص آخر مشكلة في إنشاء فئات التكوين ،

ملاحظة: لا يوجد التحقق من صحة أسماء النوع المؤهلة للتجميع. إذا أراد شخص ما إضافة سمات Advropiate للقيام بذلك ، فيرجى القيام بذلك.

using System.Configuration;

/// <summary>
/// Section for configuration known types for services.
/// </summary>
public class ServiceKnownTypesSection : ConfigurationSection
{
    /// <summary>
    /// Gets services.
    /// </summary>
    [ConfigurationProperty("declaredServices", IsDefaultCollection = false)]
    [ConfigurationCollection(typeof(DeclaredServiceElement), AddItemName = "serviceContract", CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
    public DeclaredServiceElementCollection Services
    {
        get
        {
            return (DeclaredServiceElementCollection)base["declaredServices"];
        }
    }
}

/// <summary>
/// Collection of declared service elements.
/// </summary>
public class DeclaredServiceElementCollection : ConfigurationElementCollection
{
    /// <summary>
    /// Gets the service for which known types have been declared for.
    /// </summary>
    /// <param name="key">
    /// The key of the service.
    /// </param>
    public new DeclaredServiceElement this[string key]
    {
        get
        {
            return (DeclaredServiceElement)BaseGet(key);
        }

        set
        {
            var element = BaseGet(key);
            var index = this.BaseIndexOf(element);
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }

            BaseAdd(index, value);
        }
    }

    /// <summary>
    /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </summary>
    /// <returns>
    /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    protected override ConfigurationElement CreateNewElement()
    {
        return new DeclaredServiceElement();
    }

    /// <summary>
    /// Gets the element key for a specified configuration element when overridden in a derived class.
    /// </summary>
    /// <returns>
    /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    /// <param name="element">
    /// The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for. 
    /// </param>
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((DeclaredServiceElement)element).Type;
    }
}

/// <summary>
/// The service for which known types are being declared for.
/// </summary>
public class DeclaredServiceElement : ConfigurationElement
{
    /// <summary>
    /// Gets or sets Type.
    /// </summary>
    [ConfigurationProperty("type", IsRequired = true, IsKey = true)]
    public string Type
    {
        get
        {
            return (string) this["type"];
        }

        set
        {
            this["type"] = value;
        }
    }

    /// <summary>
    /// Gets KnownTypes.
    /// </summary>
    [ConfigurationProperty("knownTypes", IsDefaultCollection = false)]
    [ConfigurationCollection(typeof(DeclaredServiceElement), AddItemName = "knownType", CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap)]
    public ServiceKnownTypeElementCollection KnownTypes
    {
        get
        {
            return (ServiceKnownTypeElementCollection)base["knownTypes"];
        }
    }
}

/// <summary>
/// A collection of known type elements.
/// </summary>
public class ServiceKnownTypeElementCollection : ConfigurationElementCollection
{
    /// <summary>
    /// Gets an known type with the specified key.
    /// </summary>
    /// <param name="key">
    /// The key of the known type.
    /// </param>
    public new ServiceKnownTypeElement this[string key]
    {
        get
        {
            return (ServiceKnownTypeElement)BaseGet(key);
        }

        set
        {
            var element = BaseGet(key);
            var index = this.BaseIndexOf(element);
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }

            BaseAdd(index, value);
        }
    }

    /// <summary>
    /// When overridden in a derived class, creates a new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </summary>
    /// <returns>
    /// A new <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    protected override ConfigurationElement CreateNewElement()
    {
        return new ServiceKnownTypeElement();
    }

    /// <summary>
    /// Gets the element key for a specified configuration element when overridden in a derived class.
    /// </summary>
    /// <returns>
    /// An <see cref="T:System.Object"/> that acts as the key for the specified <see cref="T:System.Configuration.ConfigurationElement"/>.
    /// </returns>
    /// <param name="element">
    /// The <see cref="T:System.Configuration.ConfigurationElement"/> to return the key for. 
    /// </param>
    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((ServiceKnownTypeElement)element).Type;
    }
}

/// <summary>
/// Configuration element for a known type to associate with a service.
/// </summary>
public class ServiceKnownTypeElement : ConfigurationElement
{
    /// <summary>
    /// Gets or sets TypeString.
    /// </summary>
    [ConfigurationProperty("type", IsRequired = true, IsKey = true)]
    public string TypeString
    {
        get
        {
            return (string)this["type"];
        }

        set
        {
            this["type"] = value;
        }
    }

    /// <summary>
    /// Gets or sets Type.
    /// </summary>
    public Type Type
    {
        get
        {
            return Type.GetType(this.TypeString);
        }

        set
        {
            this["type"] = value.AssemblyQualifiedName;
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top