WCF, net.tcp i svcutil

Chcąc wystawić WCF po protokole innym niż http, np.: net.tcp, i mieć możliwość wygenerowania Proxy dla naszego serwisu, musimy wykonać aktywację TCP. Czynności z tym związane opisane są na stronach MSDN.
Generalnie sprawa sprowadza się do dodania dodatkowego endpointu do naszego serwisu z bindingiem mexTcpBinding i kontraktem IMetadataExchange.

<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />

Po tych czynnościach jesteśmy w stanie wygenerować Proxy narzędziem svcutil.exe, np.:

svcutil net.tcp://localhost/MyService/Service1.svc/mex
Advertisements

Egzamin 70-515

Dzisiaj podszedłem do egzaminu 70-515 Web Applications Development with Microsoft .NET Framework 4 i udało mi się go zdać z wynikiem 940 punktów. Wynik uważam za bardzo dobry, a moje zadowolenie potęguje jeszcze fakt, że dokonałem tego przy pierwszym podejściu. Myślę, że na tym jednym egzaminie nie poprzestanę i wkrótce podejdę do kolejnych ze ścieżki dla developerów.

DisplayName attribute

Definicja atrybutu, pozwalającego na nadanie specyficznej nazwy właściwościom klasy. Jeżeli podamy resourceKey i resourceType, wówczas nazwa będzie pobierana ze zdefiniowanych resoursów.

Atrybut ten posłużył mi, podczas przygotowywania biblioteki do eksportu danych do formatu CSV na podstawie definicji klasy.
Dzięki temu atrybutowi w pliku wyjściowym generowane są nagłówki w odpowiednim języku.

    /// 
    /// Specifies the display name for a propery.
    /// 
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class DisplayNameAttribute : Attribute
    {
        private string _displayName;
        /// 
        /// Gets a display name. If ResourceKey and ResourceType are provided then this value is taken from resources.
        /// 
        public string DisplayName
        {
            get
            {
                SetDisplayNameByResourceKey();
                return _displayName;
            }
        }

        private string ResourceKey { get; set; }

        private Type ResourceType { get; set; }

        /// 
        /// Initializes a new instance of the DisplayNameAttribute class.
        /// 
        /// The display name.
        public DisplayNameAttribute(string displayName)
        {
            _displayName = displayName;
        }

        /// 
        /// Initializes a new instance of the DisplayNameAttribute class.
        /// 
        /// The resource key indicates display name in resources.
        /// The resource type where resource key is included.
        public DisplayNameAttribute(string resourceKey, Type resourceType)
        {
            ResourceKey = resourceKey;

            ResourceType = resourceType;
        }

        private void SetDisplayNameByResourceKey()
        {
            if (ResourceType == null || ResourceKey == null)
                return;

            PropertyInfo property = ResourceType.GetProperty(ResourceKey, BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic);

            if (property == null)
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.DisplayNameResources.DisplayNameAttribute_ResourceTypeDoesNotHaveProperty,
                                                                  ResourceType.FullName, ResourceKey));
            if (property.PropertyType != typeof(string))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.DisplayNameResources.DisplayNameAttribute_ResourcePropertyNotStringType,
                                                        property.Name, ResourceType.FullName));

            _displayName = (string)property.GetValue(null, null);
        }
    }

Poniżej użycie na przykładzie klasy User

public class User
    {
        public int Id { get; set; }
       
        [DisplayName("FirstName", typeof(Resources.DisplayName))]
        public string FirstName { get; set; }

        [DisplayName("Last Name")]
        public string LastName { get; set; }

        [DisplayName("DateOfBirth", typeof(Resources.DisplayName))]
        public DateTime? DateOfBirth { get; set; }        

        public string Email { get; set; }
    }

Pobranie nazwy właściwości z obiektu

        
        public static string GetName<T>(Expression<Func<T, object>> expression) 
        {
            ExpressionType type = expression.Body.NodeType;

            if (type == ExpressionType.MemberAccess)
                return ((MemberExpression)expression.Body).Member.Name;

            if (type == ExpressionType.Convert)
                return ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member.Name;

            if (type == ExpressionType.Call)
                return ((MethodCallExpression)expression.Body).Method.Name;

            throw new ArgumentException("Unknown expression type: " + type);
        }

… i użycie

var propertyName = NameHelper.GetName<Customer>(s => s.CustomerId);