How to adapt / create a method that receives an anonymous class in C#

Asked

Viewed 447 times

4

I have a method in which one of the parameters is an object of an abstract class - Objectmapper - whose purpose is to convert an object of one class into another of another class. Below, the method signature informs that the objectMapper will receive as input a Dbdatareader and return a generic T object

public T Select<T>(string query, ObjectMapper<T, DbDataReader> objectMapper)
{
    var reader = dbConnector.CreateCommand(query).ExecuteReader();

    try
    {
        return objectMapper.from(reader);
    }
    catch (Exception e)
    {
        throw e;
    }
    finally
    {
        reader.Close();
    }
}

As I come from the Java background, for cases that I don’t need to create a class, just use an anonymous class. However, it seems that C# does not provide this functionality, so I could invoke the method as follows

Select<Pessoa>("SELECT * FROM PESSOA", new ObjectMapper<Pessoa, DbDataReader>() {
    public override Pessoa from(DbDataReader reader) {
        Pessoa p = new Pessoa();

        /** Populo o objeto p a partir do objeto DbDataReader **/

        return p;
    }
});

What should you do to adapt - or even create a new method - so that I can pass an "anonymous class" to the Select method ?

UPDATE

Follows the class Objectmapper

public abstract class ObjectMapper<T, Source>
{
    public abstract T from(Source source);

    public static bool hasColumnName(DbDataReader reader, string columnName)
    {
        for (int i = 0; i < reader.FieldCount; i++)
        {
            if (reader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) 
            {
                return true;
            }
        }

        return false;
    }

    /** Outros métodos utilitários **/ 
}

This class would be an adaptation of the Rowmapper class used by the Spring framework

http://www.mkyong.com/spring/spring-jdbctemplate-querying-examples/

  • It actually provides, yes, but I wanted to understand where this comes from ObjectMapper. It’s from some ORM?

  • @Gypsy Morrison Mendez No gypsy. I will post the class

  • The class Objectmapper has some other method Abstract? The method Select needs the class Objectmapper or only to access the method from?

  • @ramaral Abstract only from method. Select method only needs to access from method. Utility methods are usually accessed by Objectmapper class instances

  • The method from access some method/property of Objectmapper?

  • @ramaral Classes that inherit Objectmapper - and consequently implement the from method - can access static methods of the Objectmapper class, such as hasColumnName

Show 1 more comment

2 answers

3


In C# you can resort to a delegate to pass a function/method to another method.

C# provides some delegates ready-to-use.

If you only need to use static methods of the class Objectmapper I suggest you do so:

State the method Select as follows:

public T Select<T>(string query, Func<DbDataReader, T> from)
{
    var reader = dbConnector.CreateCommand(query).ExecuteReader();

    try
    {
        return from(reader);
    }
    catch (Exception e)
    {
        throw e;
    }
    finally
    {
        reader.Close();
    }
}

To the method Select, in addition to the SQL string, a delegate who receives a Dbdatareader and returns an object of type T

This delegate is encapsulated using Func<T, TResult>

To call the method Select do so:

Pessoa pessoa = Select("SELECT * FROM PESSOA", reader =>
    {
        Pessoa p = new Pessoa();

        /** Populo o objeto p a partir do objeto DbDataReader **/

        return p;
    });

The code between braces is whatever you want and inside it you have access to Dbdatareader through the variable reader

1

If the goal is to provide a dynamic mapper for C#, there are already some ready, like the Automapper.

If the goal is to implement to learn, I can say that I have never seen this construction of defining the object and then implementing the body of the function, all together, at least not in C#.

If I were you, I wouldn’t define from as an abstract. Definiria virtual, allowing derived classes to reimplementate the method if necessary:

public abstract class ObjectMapper<T, TSource>
    where T: class, new()
    where TSource: DbDataReader
{
    public IEnumerable<T> From(TSource source)
    {
        if (source.HasRows)
        {
            while (source.Read())
            {
                var objeto = new T();
                for( int index = 0; index < source.FieldCount; index ++ )
                {
                    typeof(T).GetProperty(source.GetName(index)).SetValue(objeto, source.GetString(index));
                }

                yield return objeto;
            }
         }
    };

    public static bool hasColumnName(DbDataReader reader, string columnName)
    {
        for (int i = 0; i < reader.FieldCount; i++)
        {
            if (reader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase)) 
            {
                return true;
            }
        }

        return false;
    }

    /** Outros métodos utilitários **/ 
}

This example is not exactly sure, but it would be a start.

  • I actually made an adaptation of the Rowmapper used by the Spring framework. See http://www.mkyong.com/spring/spring-jdbctemplate-querying-examples/

  • Well, for educational purposes I think valid, but C# has other more interesting ways to get data and map to objects that using a DbDataReader. The micro-framework Dapper, used to implement this site we are on, is one of them.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.