Object Reference LINQ Com NHibernate

Passei por um problema muito simples, porém me atrasou pelo menos 1 dia de trabalho até descobrir o real problema.
O erro que estava ocorrendo era referente a uma query LINQ criada para ser executada pelo NHibernate(Versão 3.3.1), porém estava ocorrendo Object Reference no metodo TransformTuple, o stack Trace estava assim:

NHibernate.Exceptions.GenericADOException : Could not execute query[SQL: SQL not available]
  ----> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
  ----> System.NullReferenceException : Object reference not set to an instance of an object.
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results)
   at NHibernate.Impl.AbstractSessionImpl.List(IQueryExpression queryExpression, QueryParameters parameters)
   at NHibernate.Impl.ExpressionQueryImpl.List()
   at NHibernate.Linq.DefaultQueryProvider.ExecuteQuery(NhLinqExpression nhLinqExpression, IQuery query, NhLinqExpression nhQuery)
   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
   at Remotion.Linq.QueryableBase`1.GetEnumerator()
   at System.Linq.Enumerable.<TakeIterator>d__3a`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList(IEnumerable`1 source)
   at XXXXInfrastructure.Repository.Nhibernate.Repositorio.Repositorio.Pesquisar(Periodo periodo, Nullable`1 status, Paginacao paginacao, ref Int32 total) in EntidadeRepositorio.cs: line 59
   at Castle.Proxies.Invocations.IEntidadeRepositorio_Pesquisar.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at XXXX.Infrastructure.IOC.InterceptadorUnidadeTrabalho.Intercept(IInvocation invocation) in InterceptadorUnidadeTrabalho.cs: line 72
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IEntidadeRepositorioProxy.Pesquisar(Periodo periodo, Nullable`1 status, Paginacao paginacao, ref Int32 total)
   at XXXXX.Domain.Service.Interfaces.EntidadeServico.Pesquisar(EntradaPesquisarRequestVM entrada, ref Int32 total) in EntidadeServico.cs: line 52
   at Castle.Proxies.Invocations.IEntidadeServico_Pesquisar.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at XXXX.Infrastructure.IOC.InterceptadorUnidadeTrabalho.Intercept(IInvocation invocation) in InterceptadorUnidadeTrabalho.cs: line 72
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IEntidadeServicoProxy.Pesquisar(EntradaEntidadePesquisarRequestVM entrada, ref Int32 total)
   at XXXX.Application.Web.Api.Controllers.EntidadeController.Pesquisar(EntidadePesquisarRequestVM requetVm) in EntidadeController.cs: line 34
   at Tests.Integrated.Application.Web.Api.EntidadeTestes.Entidade_PesquisarPorStatus_DeveEfetuarPesquisaComSucesso() in EntidadeTestes.cs: line 75
--TargetInvocationException
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at NHibernate.Linq.ResultTransformer.TransformTuple(Object[] tuple, String[] aliases)
   at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.GetResultList(IList results, IResultTransformer resultTransformer)
   at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
   at NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results)
--NullReferenceException
   at lambda_method(Closure, Object[])

Depois de diversas pesquisas e sem encontrar uma solução na internet ou alguem que tivesse o mesmo erro que eu, tentei outras formas de resolver o problema como trocar para criteria a query, definir um result transform customizado para entender o problemas, interceptar a query para ver se ela estava sendo gerada com problema, porém sem sucesso.

O objeto que eu teria que retornar era assim:

   public class EntidadeDTO
    {
        public int Id { get; set; }
        public DateTime DataAbertura { get; set; }
        public DateTime? DataFechamento { get; set; }
        public StatusEntidade Status { get; set; }
        public int Totalizador1 { get; set; } //SubQuery
        public int Totalizador2 { get; set; } //SubQuery
        public int Totalizador3 { get; set; } //SubQuery
        public int Totalizador4 { get; set; }        //SubQuery
        public decimal ValorAproximado { get; set; }
        public decimal ValorFinal { get; set; } //SubQuery
    }

O erro ocorria pois a subquery que calcula o ValorFinal estava retornando null ao invez de 0, por isso ocorreu esse problema alterando para decimal? o erro parou de ocorrer, então uma lição aprendida sobre LINQ junto com NHibernate é, quando executar SubQueries tente sempre utilizar Nullable. O Objeto de retorno no final ficou assim.

   public class EntidadeDTO
    {
        public int Id { get; set; }
        public DateTime DataAbertura { get; set; }
        public DateTime? DataFechamento { get; set; }
        public StatusEntidade Status { get; set; }
        public int? Totalizador1 { get; set; } //SubQuery
        public int? Totalizador2 { get; set; } //SubQuery
        public int? Totalizador3 { get; set; } //SubQuery
        public int? Totalizador4 { get; set; }        //SubQuery
        public decimal ValorAproximado { get; set; }
        public decimal? ValorFinal { get; set; } //SubQuery
    }

Como Derrubar Conexões do PostgreeSQL(Timeout while getting a connection from pool)

Estava com o seguinte problema ocorrendo intermitente quando executava uma Function usando C# com NpgSQL: “Timeout while getting a connection from pool”, identifiquei que estava com problema para fechar as conexões ao executar a função e corrigi, porém ainda existia conexões pendentes travadas, segue comandos para executar para derrubar conexões ativas do PostgreSQL . Segue Link de referencia, eu testei nas duas versões e funcina normalmente: LINK

Até versão PostgreSQL 9.1:

SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'Nome_Banco_Dados'
  AND procpid <> pg_backend_pid();

Após versão PostgreSQL 9.2:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'Nome_Banco_Dados'
  AND pid <> pg_backend_pid();

Outra dica importante é desabilitar o Pooling na connection string que pode causar um problema em concorrencia, mas isso depende do cenario da sua aplicação, o Pooling de conexão é para fazer um cache de conexões de banco de dados mantido para que as conexões podem ser reutilizados, quando são necessárias futuras solicitações para o banco de dados. Ligado ajuda a melhorar o desempenho de executar comandos numa base de dados, porém é necessário gerenciar isso para não travar as conexões.

XmlSerializer possui erro com Array de List

Um erro desses deve afetar poucas pessoas, mas na versão atual do .NET Framework 4.5.1 ocorre um erro de object reference ao executar o codigo a seguir:

       XmlSerializer serializaer = new XmlSerializer(typeof(List<string>[]));

Ao executar esse codigo ocorre um erro do tipo System.NullReferenceException, seguindo o Stack ocorre no metodo System.Xml.Serialization.CodeGenerator.GetVariableType. O Stack Completo do erro é assim:

 

at System.Xml.Serialization.CodeGenerator.GetVariableType(Object var)
at System.Xml.Serialization.SourceInfo.InternalLoad(Type elementType, Boolean asAddress)
at System.Xml.Serialization.XmlSerializationILGen.ILGenLoad(String source, Type type)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteMemberBegin(Member[] members)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteArray(String source, String arrayName, ArrayMapping arrayMapping, Boolean readOnly, Boolean isNullable, Int32 fixupIndex, Int32 elementIndex)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteElement(String source, String arrayName, String choiceSource, ElementAccessor element, ChoiceIdentifierAccessor choice, String checkSpecified, Boolean checkForNull, Boolean readOnly, Int32 fixupIndex, Int32 elementIndex)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteMemberElementsIf(Member[] members, Member anyElement, String elementElseString)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteMemberElements(Member[] members, String elementElseString, String elseString, Member anyElement, Member anyText)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteArray(String source, String arrayName, ArrayMapping arrayMapping, Boolean readOnly, Boolean isNullable, Int32 fixupIndex, Int32 elementIndex)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteElement(String source, String arrayName, String choiceSource, ElementAccessor element, ChoiceIdentifierAccessor choice, String checkSpecified, Boolean checkForNull, Boolean readOnly, Int32 fixupIndex, Int32 elementIndex)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteMemberElementsIf(Member[] members, Member anyElement, String elementElseString)
at System.Xml.Serialization.XmlSerializationReaderILGen.WriteMemberElements(Member[] members, String elementElseString, String elseString, Member anyElement, Member anyText)
at System.Xml.Serialization.XmlSerializationReaderILGen.GenerateTypeElement(XmlTypeMapping xmlTypeMapping)
at System.Xml.Serialization.XmlSerializationReaderILGen.GenerateElement(XmlMapping xmlMapping)
at System.Xml.Serialization.TempAssembly.GenerateRefEmitAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence)
at System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence)
at System.Xml.Serialization.XmlSerializer.GenerateTempAssembly(XmlMapping xmlMapping, Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
at System.Xml.Serialization.XmlSerializer..ctor(Type type)
at MeuPrograma.Program.Main(String[] args) in d:\MeuPrograma\Program.cs:line 47
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

Porém encontrar o erro assim é muito simples, mas a serialização de XML como mostrada é utilizada em diversos outros lugares como WebAPI e WebServices(Asmx). No meu caso encontrei esse erro em um Asmx graças a esse link(que está em Frances) consegui identificar que um metodo estava retornar um objeto com Array de Lista e foi identificado o problema. Não é permitido utilizar array de List como parametro ou retorno de metodos ASMX pois pode ocrrer esse problema na serialização do cliente.

Para resolver esse problema a unica possibilidade é transformar este Array de List em um Objeto, ficando até mais organizado, ou se quiser deixar porcamente pode ser utilizado um List de List que o XmlSerializer vai funcionar.

Diferença entre override e new no C#

Vamos falar sobre os modificadores override e new. Quando utilizamos o override é possivel utilizarmos a tecnica de polimorfismo, como não declarar um objeto do tipo concreto apenas utilizar a abstração. Porém no caso do modificador new ele é apenas utilizado quando a variavel é especifica do tipo concreto. Para exemplificar será criado duas classes uma abstrata e uma concreta como a seguir:

 public abstract class MyBaseObject
    {
        public  abstract void MethodForOverride2();

        public virtual void MethodForOverride()
        {
            Console.WriteLine("MethodForOverride of MyBaseObject");
        }

        public void MethodForNew()
        {
            Console.WriteLine("MethodForNew of MyBaseObject");
        }


    }

    public class MyFirstConcreteObject : MyBaseObject
    {
        public override void MethodForOverride2()
        {
            Console.WriteLine("MethodForOverride2 of MyFirstConcreteObject");
        }

        public override void MethodForOverride()
        {
            Console.WriteLine("MethodForOverride of MyFirstConcreteObject");
        }
        public new void MethodForNew()
        {
            Console.WriteLine("MethodForNew of MyFirstConcreteObject");
        }
    }

Após isso faça a chamada assim em uma console application para executar os metodos:

            MyBaseObject myBaseObject = new MyFirstConcreteObject();
            MyFirstConcreteObject myConcreteObject = new MyFirstConcreteObject();

            Console.WriteLine("myBaseObject");
            myBaseObject.MethodForNew();
            myBaseObject.MethodForOverride();
            myBaseObject.MethodForOverride2();

            Console.WriteLine("");
            Console.WriteLine("myConcreteObject");
            myConcreteObject.MethodForNew();
            myConcreteObject.MethodForOverride();
            myConcreteObject.MethodForOverride2();

Executar esse codigo deve ter um retorno como na imagem. É possivel perceber que o metodo utilizando override sempre é utilizado da classe concreta, porém quando utilizado o modificador new depende do tipo de variavel que está sendo declarada.

Execucao

Todo o código deste post está no github neste link.

Definir Parametro generico por tipo(type)

Falando sobre reflection um necessidade que encontrei e vou colocar aqui é definir um parametro generico de uma classe por um Type, para isso podemos usar o metodo MakeGenericType. O conteudo é bem simples então vou apenas postar o codigo de como fazer sem muita necessidade de explicação.

            Type typeGenericList = typeof(MyClass);
            var ListWithoutType = typeof(IList<>); // this is a list generic without the generic type set
            var ListWithType = ListWithoutType.MakeGenericType(tipoEntidade); // this is a list generic with the generic parametier of MyClass IList<MyClass>

Iniciando com StructureMap

StructureMap é uma biblioteca open-source para fazer Injeção de dependência/ inversão de controle, ela é muito simples de configurar e utilizar, comparada com outras.  Simplificando bem para o que ela pode ser utilizada, ela é utilizada para criar um objeto de uma interface sem conhecer a classe concreta que será utilizada.

Para adicionar a biblioteca pode ser feita pelo Nuget com as versões mais atuais do visual studio ou pode ser feito o download da dll no próprio site da biblioteca.

Dentro da biblioteca a classe mais importante é a ObjectFactory, essa classe é utilizada para configurar qual objeto deve ser criado para qual interface, e quando for necessário retornar um objeto para uma interface ela também é utilizada.

Exemplo

Em uma solução normalmente temos projetos em contexto Web e outros locais(windows services, Console Applications entre outros) que utilizam as mesmas classes, porém é comum ocorrer o problema de dentro de uma dessas classes encontrar um comentários mais ou menos assim “Método deve ser chamado apenas por projetos Web” ou até mesmo diversas condições para que o método pegue as informações de um lugar ou de outro. Isso ocorre com diversas informações mas nesse caso utilizaremos apenas para algumas configurações exatamente para exemplificar.

Primeiro vamos definir o comportamento da nossa interface e uma classe que irá conter as configurações que desejamos buscar. Nossa interface IConfiguracao terá apenas um método chamado PegarConfiguracao que deve retornar uma classe com as configurações do ambiente, como o código abaixo demontra:

public interface IConfigurations
{
 ConfigurationsInfo PegarConfiguracao();
}

public class ConfigurationsInfo
{
 public TipoAmbiente Ambiente { get; set; }
 public string NomeUsuario { get; set; }
}

public enum TipoAmbiente
{
 Local,
 Web
}

Com a interface criada agora deve ser criado as classes concretas para essa interface, nesse caso vamos criar duas WebConfiguration e LocalConfiguration. Uma deverá retornar informações armazenadas na sessão utilizada pelo ASP.Net e a outra deverá retornar informações armazenadas em uma variável estática. A implementação das classe fica assim

public class WebConfiguration : IConfigurations
{
	public ConfigurationsInfo PegarConfiguracao()
	{
		if (HttpContext.Current.Session["NomeUsuario"] == null)
		{
			HttpContext.Current.Session["NomeUsuario"] = "Nome do usuario na Web";
		}
		return new ConfigurationsInfo()
			   {
				   Ambiente = TipoAmbiente.Web,
				   NomeUsuario = HttpContext.Current.Session["NomeUsuario"].ToString()
			   };
	}
}

public class LocalConfiguration : IConfigurations
{
	private static string nomeUsuario;
	public ConfigurationsInfo PegarConfiguracao()
	{
		if (nomeUsuario == null)
		{
			nomeUsuario = "Nome do usuario Local";
		}
		return new ConfigurationsInfo()
			   {
				   Ambiente = TipoAmbiente.Local,
				   NomeUsuario = nomeUsuario
			   };
	}
}

Até agora a unica coisa utilizada foi o básico de orientação a objetos. Agora nos vamos começar com o StructureMap, cria uma classe estática chamada Mapeador(Nome besta exatamente para fixar), essa classe será responsável por fazer a configuração de qual classe concreta deve ser criada para a interface, e também será utilizada para criar um objeto a partir do tipo da interface passada. A configuração será no método chamado Map, dentro dele será chamado o método configure o ObjectFactory, que permite passar a interface e qual o tipo concreto que deve ser criado. O outro método criado será o método Get que irá retornar o objeto a partir da interface. A classe irá ficar assim:

public static class Mapeador
{
	public static void Map()
	{
		
		if (HttpContext.Current == null)
		{
			ObjectFactory.Configure(x =>
			 x.For(typeof(IConfigurations)).Use(typeof(LocalConfiguration)));
		}
		else
		{
			ObjectFactory.Configure(x =>
			 x.For(typeof(IConfigurations)).Use(typeof(WebConfiguration)));
		}

	}

	public static T Get<T>()
	{
		return ObjectFactory.GetInstance<T>();
	}
}

Agora a melhor forma de testar é criar duas aplicações uma Local(no nosso caso será uma console) e uma Web e efetuar a criação o objeto e ver se está funcionando como deve. Primeiro crie uma aplicação console, nela é apenas necessário chamar primeiro o metodo Map da classe Mapeador e depois o Metodo Get. O codigo da aplicação console deve ficar assim:

	Mapeador.Map();
	IConfigurations configurations = Mapeador.Get<IConfigurations>();
	var config = configurations.PegarConfiguracao();
	Console.WriteLine(config.Ambiente + " - Usuario:" + config.NomeUsuario);

	Console.ReadKey();

A unica diferença entre a aplicação console e a aplicação web é o local que deve ser chamado o metodo Map, pois não é uma boa pratica sempre executar o metodo map, isso pode gerar repetição de codigo desnecessário e maior processamento no servidor. O melhor lugar para colocar a configuração é no arquivo Global.asax no metodo Application_Start que irá ser executado apenas quando o site é iniciado.

 

Todo o código deste post está no github neste link.

O que é CDN ?

CDN (Content Delivery Network) são links disponibilizados, normalmente por grandes empresas de tecnologia, com arquivos de bibliotecas comuns de javascript ou css, Isso é extremamente útil para evitar desperdício de banda com download de arquivos comuns como Jquery, NodeJS entre outros. Empresas como Microsoft e Google possuem diversos Links disponibilizados com varias versões do JQuery.

As maiores vantagens em se utilizar CDN ao invés de colocar esses arquivos diretamente no projeto são:

  • Se o usuário acessou qualquer site que utilize o mesmo CDN que você, ele não precisará baixar esse arquivo js novamente.
  • Arquivo em diversos servidores, com isso o download dele é mais rápido
  • Não utiliza a banda do seu servidor para envio do arquivo js
  • Utilizar é de graça e não necessita de nenhum pagamento

Esse é um exemplo de como fica a referencia para um CDN em sua aplicação:

<script src="netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"></script>

Algumas páginas com mais informações de CDN de determinadas empresas:

Princípio de Substituição de Liskov (Liskov substitution principle – LSP)

O principio de substituição de Liskov define :

“Os subtipos devem ser substituíveis pelos seus tipos base”

Esse é um principio q confunde muitos programadores, porém é bem simples depois que se entende ele. Um termo muito utilizado no aprendizado do conceito de herança é o termo “É-um”. Esse termo é muito amplo para definição de um subtipo. A melhor forma de definição para subtipo é substituível, quando a substituição é definida por uma interface explicitamente ou implicitamente.

Desing by contract é uma pratica que ajuda a seguir esse principio. Ela define para que não seja criado variáveis de classes concretas, deve ser criado as variáveis a partir de contratos explícitos.

Esse principio alerta com o uso incorreto de polimorfismo, é necessário ter uma visão muito correta para generalizar ou especificar uma propriedade ou um parâmetro de um método em uma classe. Para deixar os termos que estou usando mais claros:

  • Generalizar: Quando a variável em questão é um tipo base, uma interface, uma classe abstrata ou qualquer outro tipo de objeto que é possível passar um objeto derivado dele.
  • Especializar: Quando a variável em questão é o objeto concreto, só é possível passar um objeto daquele determinado tipo.

A parte mais importante para entender esse principio, é que não se utilizar uma classe base quando alguma classe derivada dele não pode ser substituível por ele. Caso a classe derivada remova alguma funcionalidade da classe base ou ocasione um erro nas funcionalidades da classe base.

Exemplo:Vou tentar mostrar em uma cenário bem bestinha, mas é para entender realmente o conceito. Voce tem uma classe pessoa e ela tem dois métodos CalcarPeDireito e CalcarPeEsquerdo. Os dois metodos recebem dois parametros um Sapato(classe abstrata) e uma Meia(classe abstrata), fazendo o uso de generalização.  A estrutura de classes do Sapato e da Meia são essas:

    /// <summary>
    /// Meia
    /// </summary>
    public abstract class Sock
    {
        protected Sock()
        {

        }
        public abstract string Side { get; }

    }

    public  class RightSock : Sock
    {
        public RightSock()
        {

        }
        public override string Side
        {
            get { return "Right"; }
        }
    }

    public  class LeftSock : Sock
    {
        public LeftSock()
        {

        }
        public override string Side
        {
            get { return "Left"; }
        }
    }

    /// <summary>
    /// Sapato
    /// </summary>
    public abstract class Shoe
    {
        public abstract string Side { get; }

        protected Shoe()
        {

        }
    }

    public class LeftShoe : Shoe
    {
        public LeftShoe()
        {

        }
        public override string Side
        {
            get { return "Left"; }
        }
    }

    public class RightShoe : Shoe
    {
        public RightShoe()
        {

        }
        public override string Side
        {
            get { return "Right"; }
        }
    }

A classe pessoa está desenvolvida assim:

    public static class Person
    {
        /// <summary>
        /// Calçar Pé esquerdo
        /// </summary>
        /// <param name="shoe"> Can't be any show only the left</param>
        /// <param name="sock"> There is no diference</param>
        public static void PuttingOnLeftFootBreakingLSP(Shoe shoe, Sock sock)
        {
            Console.WriteLine("Putting socks {0} on the left foot!", sock.Side);
            if (shoe.Side != "Left")
            {
                Console.WriteLine("Wrong foot!");
            }
            else
            {
                Console.WriteLine("Putting shoes {0} on the left foot!", shoe.Side);
            }
        }

        /// <summary>
        /// Calçar Pé Direito
        /// </summary>
        /// <param name="shoe"></param>
        /// <param name="sock"> There is no diference</param>
        public static void PuttingOnRightFootBreakingLSP(Shoe shoe, Sock sock)
        {
            Console.WriteLine("Putting socks {0} on the righ foot!", sock.Side);
            if (shoe.Side != "Right")
            {
                Console.WriteLine("Wrong foot!");
            }
            else
            {
                Console.WriteLine("Putting shoes {0} on the righ foot!", shoe.Side);
            }
        }
    }

Com isso nada impede de eu fazer isso no codigo:

     Person.PuttingOnLeftFootBreakingLSP(new RightShoe(), new RightSock());
     Person.PuttingOnRightFootBreakingLSP(new LeftShoe(), new RightSock());

Ok, agora para resolver esse problema e seguir o principio de Substituição de Liskov como podemos alterar isso? Muito simples, utilizaremos a generalização ainda é possível, no caso no paramento da meia, pois a meia não tem problema se colocar invertido. E usaremos a especialização onde é necessário, no caso no sapato, utilizaremos em em seus respectivos  métodos o sapato do lado correto, como mostra o código a seguir:

 public static class Person
    {
        /// <summary>
        /// Calçar Pé esquerdo
        /// </summary>
        /// <param name="shoe"></param>
        /// <param name="sock"></param>
        public static void PuttingOnLeftFootUsingLSP(LeftShoe shoe, Sock sock)
        {
            Console.WriteLine("Putting socks {0} on the left foot!", sock.Side);
            Console.WriteLine("Putting shoes {0} on the left foot!", shoe.Side);
        }

        /// <summary>
        /// Calçar Pé Direito
        /// </summary>
        /// <param name="shoe"></param>
        /// <param name="sock"></param>
        public static void PuttingOnRightFootUsingLSP(RightShoe shoe, Sock sock)
        {
            Console.WriteLine("Putting socks {0} on the righ foot!", sock.Side);
            Console.WriteLine("Putting shoes {0} on the righ foot!", shoe.Side);
        }

    }

Assim quando um desenvolvedor utilizar essa classe ele pode utilizar o polimorfismo com os parâmetros possíveis, mais os que não é possível generalizar ele é obrigado a passar a classe concreta corretamente, isso da muito mais segurança na codificação. Isso faz com que aquele código de forma incorreta na classe Pessoa não seja mais permitido.

Todo o código deste post está no github neste link.

Criar eventos ao adicionar item em List C#

Isso é algo realmente chato as vezes, você precisa fazer uma ação antes de que qualquer item seja inserido em determinada lista. Isso as vezes se torna bem chato se o sistema não tem um encapsulamento das propriedades bem organizado.

Tem um projeto no Github(HAL – Help a lot) exatamente com uma coleção que faz isso, eu iniciei esse projeto agrupar funções corriqueiras, que as vezes é necessário criar em diversos sistemas, ou cada empresa tem sua DLL mágica que tem as funções básicas. O código está totalmente aberto quem quiser olhar o código, tem alguma sugestão ou quer ajudar no desenvolvimento só entrar em contato comigo e pode começar a desenvolver.  Caso queria fazer o download Apenas  DLL.

Bom vamos ao problema, precisamos de uma lista que precisa interceptar a ação dos métodos Add, Insert, Remove e RemoveAt de uma lista para poder colocar o evento antes ou depois dessas ações. O que vou fazer é criar uma classe genérica que implementa IList<T> e aplicar o padrão de projetos Proxy para interceptar as ações necessárias. O código ficara assim:

    public class HalList<T> : IList<T>
    {
        public delegate void AddItemDelegate(T item);
        public delegate void RemoveItemDelegate(T item);

        public delegate void InsertItemDelegate(int index, T item);
        public delegate void RemoveAtItemDelegate(int index, T item);

        public event InsertItemDelegate BeforeInsertItem;
        public event InsertItemDelegate AfterInsertItem;

        public event RemoveAtItemDelegate BeforeRemoveAtItem;
        public event RemoveAtItemDelegate AfterRemoveAtItem;

        public event AddItemDelegate BeforeAddItem;
        public event AddItemDelegate AfterAddItem;

        public event RemoveItemDelegate BeforeRemoveItem;
        public event RemoveItemDelegate AfterRemoveItem;

        private IList<T> _list;

        public HalList()
        {
            _list = new List<T>();
        }

        public IEnumerator<T> GetEnumerator()
        {
            return _list.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void Add(T item)
        {
            if (BeforeAddItem != null)
                BeforeAddItem(item);

            _list.Add(item);

            if (AfterAddItem != null)
                AfterAddItem(item);
        }

        public void Clear()
        {
            _list.Clear();
        }

        public bool Contains(T item)
        {
            return _list.Contains(item);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            _list.CopyTo(array, arrayIndex);
        }

        public bool Remove(T item)
        {
            if (BeforeRemoveItem != null)
                BeforeRemoveItem(item);

            bool ret = _list.Remove(item);

            if (AfterRemoveItem != null)
                AfterRemoveItem(item);
            return ret;
        }

        public int Count
        {
            get { return _list.Count(); }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public int IndexOf(T item)
        {
            return _list.IndexOf(item);
        }

        public void Insert(int index, T item)
        {
            if (BeforeInsertItem != null)
                BeforeInsertItem(index, item);

            _list.Insert(index, item);

            if (AfterInsertItem != null)
                AfterInsertItem(index, item);
        }

        public void RemoveAt(int index)
        {

            if (_list.Count <= index)
                throw new HalException("Index out of range on the List!");

            T item = _list[index];

            if (BeforeRemoveAtItem != null)
                BeforeRemoveAtItem(index, item);

            _list.RemoveAt(index);

            if (AfterRemoveAtItem != null)
                AfterRemoveAtItem(index, item);
        }

        public T this[int index]
        {
            get { return _list[index]; }
            set { _list[index] = value; }
        }
    }

Pode ser questionado o motivo de deixar tudo separa, mas estou ainda pensando se vou implementar alguma coisa diferente para cada um ou colocar em todos, esse ainda é o código inicial no projeto e pode ser alterado, mas esse código já está testado.