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, или тебе причин хватит?
агерон Ну, это больше похоже на "мне нравиться так, а вот тебе нравиться так". Слишком много строк кода для одного класса? Плохо это или нет, но это реальность. Ты код .NET Framework видел? Там присутствуют классы с тысячами строк кода. И ничего, все живы. Разделение на логические слои? Абстракции ради абстракций? Я не сторонник лишних сущностей в коде. Лишь когда явно что-то выделяется, тогда можно реализовать новую сущность. Лишние классы? Возможно. Но тот же HtmlHelper мне уже не раз помогал, он для этого и создан. А WinInet не заменяется другим классом, посмотри сначала, что он делает. HttpMethod не заменяется другим перечислением, посмотри сначала их различия, да и удобней написать так, чем WebRequestMethods. CookiesDictionary не заменяется CookiesContainer, потому-что они совсем разные, у меня другой способ работы с куки. Я уже в любом случае не буду переписывать код. Даже если меня вдруг осенит и на меня снизойдут шаблоны проектирования. Просто захотелось увидеть ужас. Такие дела.
Что ж ты мне не веришь и что я говорю глупости.... тогда читай и смотри 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
В некоторых местах просто лишний код вместо использования стандартных классов 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
Вышла новая версия. Удалено всё лишнее, исправил кое-какие баги и добавил релиз: 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
О, спасибо, юзаю! Вместо нулевой длинны какую-то левую поставил, чтобы запрос отправлялся(принимался т.е. без ошибки). Спасибо за библиотеку.