xNet - библиотека классов под .NET Framework

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by X-rus, 12 May 2011.

  1. X-rus

    X-rus Member

    Joined:
    22 Dec 2010
    Messages:
    88
    Likes Received:
    22
    Reputations:
    4
    Хотелось бы увидеть конкретный пример ужасного и как это ужасное сделать прекрасным.
     
  2. агерон

    агерон New Member

    Joined:
    24 Oct 2009
    Messages:
    4
    Likes Received:
    3
    Reputations:
    5
    0) классы по 1000 строк очень способствуют тому что бы их выбросить нафиг, даже незадумываясь что там написано ибо разбераться в этом говнокоде... увольте
    1) нет разделения на логические слои
    2) слишком много проверок через if, код из за этого грязный, и макароноподобный
    3) дубляж кода
    4) пространства имен состоящие из 1 класа это круто :)
    5) StringDictionary - заменяеться на Dictionary<string,string>
    6) CryptographyHelper - ненужная оболчка над System.Security.Cryptography, нигде не используеться в библиотеке
    7) все пляски с класами SafeNativeMethods и WinInet заменяються стандартной и коректной реализацией IWebProxy;
    8) ProxyHelper с 1 методом нафиг нужен, переносим метод в ProxyClient
    9) HtmlHelper - нафиг, нигде не используеться в библиотеке
    10) DownloadProgressChangedEventArgs/UploadProgressChangedEventArgs - близнецы - братья заменяеться на один ProgressChangedEventArgs
    11) CookiesDictionary заменяеться расширением CookiesContainer
    12) перечесление HttpMethod заменяеться значениями из System.Net.WebRequestMethods.Http;

    P. S. дальше продолжать?:-D, или тебе причин хватит?
     
    geograph and GRRRL Power like this.
  3. X-rus

    X-rus Member

    Joined:
    22 Dec 2010
    Messages:
    88
    Likes Received:
    22
    Reputations:
    4
    агерон
    Ну, это больше похоже на "мне нравиться так, а вот тебе нравиться так".

    Слишком много строк кода для одного класса? Плохо это или нет, но это реальность. Ты код .NET Framework видел? Там присутствуют классы с тысячами строк кода. И ничего, все живы.

    Разделение на логические слои? Абстракции ради абстракций? Я не сторонник лишних сущностей в коде. Лишь когда явно что-то выделяется, тогда можно реализовать новую сущность.

    Лишние классы? Возможно. Но тот же HtmlHelper мне уже не раз помогал, он для этого и создан. А WinInet не заменяется другим классом, посмотри сначала, что он делает. HttpMethod не заменяется другим перечислением, посмотри сначала их различия, да и удобней написать так, чем WebRequestMethods. CookiesDictionary не заменяется CookiesContainer, потому-что они совсем разные, у меня другой способ работы с куки.

    Я уже в любом случае не буду переписывать код. Даже если меня вдруг осенит и на меня снизойдут шаблоны проектирования. Просто захотелось увидеть ужас.

    Такие дела. :)
     
  4. агерон

    агерон New Member

    Joined:
    24 Oct 2009
    Messages:
    4
    Likes Received:
    3
    Reputations:
    5
    Что ж ты мне не веришь и что я говорю глупости....
    тогда читай и смотри
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace EventsLibrary
    {
        public interface IEvent<TInterface, TEventArgs> where TEventArgs : EventArgs
        { Lazy<ExplicitlyEvent<TInterface, TEventArgs>> Event { get; set; } }
    
        public interface IFireEvent<TInterface, TEventArgs> where TEventArgs : EventArgs
        { void FireEvent(object sender, TEventArgs e); }
    }
    
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace EventsLibrary
    {
        public class EventArgs<TCLass> : EventArgs
        {
            public TCLass DataContainer { get; protected set; }
    
            public EventArgs(TCLass dataContainer)
            { DataContainer = dataContainer; }
        }
    
        public interface IException { }
        public class ExceptionEventArgs : EventArgs<Exception> { public ExceptionEventArgs(Exception exception) : base(exception) { } }
    }
    
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace EventsLibrary
    {
        public class EmptyEvent<T> where T : EventArgs
        {
            protected EmptyEvent() { }
    
            private sealed class EmptyEventCreator
            {
                private static readonly Lazy<EventHandler<T>> empty = new Lazy<EventHandler<T>>(() => { return delegate { }; });
    
                public static Lazy<EventHandler<T>> Instance { get { return empty; } }
            }
    
            public static Lazy<EventHandler<T>> EmptyHandlerEvent
            {
                get { return EmptyEventCreator.Instance; }
            }
        }
    }
    
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace EventsLibrary
    {
        public class ExplicitlyEvent<TInterface, TEventArgs>:IFireEvent<TInterface,TEventArgs>, IDisposable where TEventArgs:EventArgs 
        {
            void IFireEvent<TInterface, TEventArgs>.FireEvent(object sender, TEventArgs e)
            { Event(sender, e); }
    
            public void Dispose()
            { Event -= EmptyEvent<TEventArgs>.EmptyHandlerEvent.Value; }
    
            public event EventHandler<TEventArgs> Event = EmptyEvent<TEventArgs>.EmptyHandlerEvent.Value;
        }
    }
    
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace EventsLibrary
    {
        public static class ExtensionClasses
        {
            public static void AddEventHandler<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject, EventHandler<TEventArgs> eventHandler) where TEventArgs : EventArgs
            { interfaceObject.Event.Value.Event += eventHandler; }
    
            public static void RemoveEventHandler<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject, EventHandler<TEventArgs> eventHandler) where TEventArgs : EventArgs
            { interfaceObject.Event.Value.Event -= eventHandler; }
    
            public static void FireEvent<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject, object sender, TEventArgs e) where TEventArgs : EventArgs
            { ((IFireEvent<TInterface, TEventArgs>)interfaceObject.Event.Value).FireEvent(sender, e); }
    
            public static void CreateEvent<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject) where TEventArgs : EventArgs
            { interfaceObject.CreateEvent(new Lazy<ExplicitlyEvent<TInterface, TEventArgs>>(() => { return new ExplicitlyEvent<TInterface, TEventArgs>(); })); }
            
            public static void CreateEvent<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject, Lazy<ExplicitlyEvent<TInterface, TEventArgs>> Event) where TEventArgs : EventArgs
            { interfaceObject.Event = Event; }
    
            public static Lazy<ExplicitlyEvent<TInterface, TEventArgs>> GetEvent<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject) where TEventArgs : EventArgs
            { return interfaceObject.Event; }
            
            public static void DisposeEvent<TInterface, TEventArgs>(this IEvent<TInterface, TEventArgs> interfaceObject) where TEventArgs : EventArgs            
            { interfaceObject.Event.Dispose(); }
        }
    
        public static class LazyDisposable
        {
            public static void Dispose<TObject>(this Lazy<TObject> lazyObject)
            {
                if (lazyObject.IsValueCreated)
                    if (lazyObject.Value is IDisposable)
                        ((IDisposable)lazyObject.Value).Dispose();
            }
        }
    }
    
    Эта библиотека умеет "всего ничего" - мягкое управление событиями для любого обьекта который просто обьявит интерфейс IEvent с нужными для него (обьекта) интерфейсом - меткой и результатом события
    простой пример такого класса:
    Code:
    using System;
    using EventsLibrary;
    
    namespace Tests
    {
        public interface ITest {}
    
        public class TestEvent: IEvent<ITest, EventArgs<string>>, IDisposable
        {
            public TestEvent()  { this.CreateEvent<ITest, EventArgs<string>>(); }
    
            public void Dispose() { this.DisposeEvent<ITest, EventArgs<string>>(); }
    
            Lazy<ExplicitlyEvent<ITest, EventArgs<string>>> IEvent<ITest, EventArgs<string>>.Event { get; set; }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                TestEvent testEvent = new TestEvent();
                testEvent.AddEventHandler<ITest, EventArgs<string>>(new EventHandler<EventArgs<string>>((object sender, EventArgs<string> e)=>
                {
                    Console.WriteLine(e.DataContainer);
                    Console.ReadLine();
                }));
                testEvent.FireEvent<ITest, EventArgs<string>>(testEvent, new EventArgs<string>("Hello World!!!"));
            }
        }
    }
    
    вся прелесть этого подхода состоит всего в нескольких вещах
    1) ленивая инициализация обьекта события (System.Lazy ага :))
    2) не нужны проверки события на null для зажигания (ооо как много в этом слове NULL :-D)
    3) "мягкое" управление событием из любого места прогрвммы (добавление, удаление обработчика, зажигание события)
    4) не морочишся названиями событий, на одну интерфейс - метку можно повесить сколько угодно событий
    5) ну и так по мелочи... контейнер EventArgs для любого типа + ленивый Disposable
    Вот тебе коректный и расширяемый код, а то что ты написал, это так... для учебы и не более, по этому читай те книги о которых я упомянул, может умнее станешь и сам ужаснешься тому беспределу в коде что написал

    P. S. и да это только маленькая библиотека которую я использую в своих проектах, есть еще и другие :-D
     
    1 person likes this.
  5. Radzhab

    Radzhab New Member

    Joined:
    12 Sep 2011
    Messages:
    9
    Likes Received:
    0
    Reputations:
    0
    Проект умер как я понимаю? Где можно найти автора?
     
  6. Mandyson

    Mandyson New Member

    Joined:
    20 Mar 2011
    Messages:
    6
    Likes Received:
    0
    Reputations:
    0
    У библиотеки баг с заголовком Content-Leght, невозможно установить другой.
    Автор появитесь))
     
    #26 Mandyson, 21 Jan 2015
    Last edited: 21 Jan 2015
  7. DeepBlue7

    DeepBlue7 Elder - Старейшина

    Joined:
    2 Jan 2009
    Messages:
    359
    Likes Received:
    50
    Reputations:
    12
    В некоторых местах просто лишний код вместо использования стандартных классов CBL.

    Например:

    Code:
    // Если в строке не присутствуют символы, которые нужно закодировать.
                if ((spaceCount == 0) && (otherCharCount == 0))
                {
                    return str;
                }
    
                int bufferIndex = 0;
                byte[] buffer = new byte[bytes.Length + (otherCharCount * 2)];
    
                for (int i = 0; i < bytes.Length; i++)
                {
                    char c = (char)bytes[i];
    
                    if (IsUrlSafeChar(c))
                    {
                        buffer[bufferIndex++] = bytes[i];
                    }
                    else if (c == ' ')
                    {
                        buffer[bufferIndex++] = (byte)'+';
                    }
                    else
                    {
                        buffer[bufferIndex++] = (byte)'%';
                        buffer[bufferIndex++] = (byte)IntToHex((bytes[i] >> 4) & 15);
                        buffer[bufferIndex++] = (byte)IntToHex(bytes[i] & 15);
                    }
                }
    
    HttpUtility.UrlEncode (смотри https://msdn.microsoft.com/ru-ru/library/system.web.httputility.urlencode(v=vs.90).aspx
     
  8. myrz

    myrz Member

    Joined:
    22 Jun 2008
    Messages:
    99
    Likes Received:
    28
    Reputations:
    0
    Короче установка Content-Leght и Content-Type не удаётся, способов не вижу, гугл не помогает
     
  9. X-rus

    X-rus Member

    Joined:
    22 Dec 2010
    Messages:
    88
    Likes Received:
    22
    Reputations:
    4
    Вышла новая версия. Удалено всё лишнее, исправил кое-какие баги и добавил релиз: https://github.com/X-rus/xNet/releases

    Нулевой Content-Leght теперь отправляется автоматически. Задать Content-Type можно здесь:
    public HttpResponse Post(string address, string str, string contentType)
    public HttpResponse Post(string address, byte[] bytes, string contentType = "application/octet-stream")

    Ещё есть класс HttpContent, который возвращает длину и тип контента. Можно от него наследовать или использовать BytesContent: https://github.com/X-rus/xNet/blob/master/xNet/~Http/~Content/HttpContent.cs
     
    z668 and ChymeNik like this.
  10. myrz

    myrz Member

    Joined:
    22 Jun 2008
    Messages:
    99
    Likes Received:
    28
    Reputations:
    0
    О, спасибо, юзаю! Вместо нулевой длинны какую-то левую поставил, чтобы запрос отправлялся(принимался т.е. без ошибки). Спасибо за библиотеку.