Supongamos que deseo heredar de System.Data.SqlClient.SqlTransaction
que es sellado. Supongamos que quiero simplemente poner un contenedor alrededor de SqlTransaction
y siempre usar MyTransaction
en lugar de SqlTransaction
. ¿Existe alguna forma de que pueda emitir MyTransaction
a SqlTransaction
utilizando un operador de ampliación/implícito?¿Hay alguna forma de FALSIFICAR herencia en C#/VB.NET?
Respuesta
Si realmente desea la conversión implícita (aunque yo no lo recomiendo, ya que es una idea horrible y un diseño horrible, OMI), se puede hacer algo como esto:
class MyTransaction
{
private readonly SqlTransaction _transaction;
public MyTransaction(SqlConnection conn)
{
_transaction = conn.BeginTransaction();
}
public SqlTransaction Transaction
{
get
{
return _transaction;
}
}
public static implicit operator SqlTransaction(MyTransaction t)
{
return t.Transaction;
}
}
Lamentablemente esto está en VB.NET y su operador de ensanchamiento no parece funcionar ya que C# es "implícito" lo que acabo de descubrir, pero también estaba pensando en esta ruta ... Aunque como dijiste, tampoco me gusta ... – Denis
@Denis podría intentar codificar la clase en C# y luego usar la DLL en su aplicación VB –
@Denis Code en C#, usar Refelctor para desmontar en VB y verá la sintaxis. – TomTom
Puede crear una clase que tenga una variable de transacción interna y luego exponer los métodos y las propiedades. Algo así como esto:
public class MyTransaction
{
System.Data.SqlTransaction myTx = someConnection.CreateTransaction();
public void CommitTransaction() : {
myTx.CommitTransaction()
}
}
También puede hacer que herede de DbTransaction y vuelva a grabar los procedimientos abstractos y virtuales para utilizar la variable myTx interior, pero empieza a ser un poco compleja sin razón aparente ...
¡Absolutamente! : -Þ Pero si el hombre quiere envolver una transacción, ¡puede haber una razón! –
Solo porque quiera hacerlo, y aunque sea posible, no significa que deba hacerlo. –
@Ramhound Estoy de acuerdo, pero igual es una buena forma de aprender para otros casos más adecuados donde una solución como esta es adecuada –
Si solo está interesado en agregar métodos adicionales a una clase, puede usar métodos de extensión. Eso no le dará acceso a ningún estado interno ni le permitirá anular comportamientos, pero le permitirá agregar funcionalidades limitadas. No estoy al tanto de ninguna forma de heredar de una clase sellada.
Puede crear un verdadero objeto envoltorio como otros lo han mencionado, pero no podrá usarlo polimórficamente en lugar del objeto original.
Esto está en .NET 2.0 entonces no hay métodos de extensión ... Pero también necesito hacer un seguimiento de cosas desde la creación, por lo que los métodos de extensión no funcionarán de todos modos. – Denis
No es que esto importe debido a .net 2, pero los métodos de extensión pueden rastrear datos de objetos independientes utilizando un diccionario descodificado del primer parámetro del método de extensión (el objeto manipulado). Esto puede ofrecer un conjunto de datos "particionados" que se asemeja al estado interno pero que se almacena de forma externa al objeto. Se puede acceder a los miembros internos a través de la reflexión, por lo que puede hacer algunas cosas interesantes dependiendo de qué tan "feo" esté dispuesto a permitir que se obtenga el código. –
Espero que no te importe, pero agregué una etiqueta .net2.0 a tu pregunta para que otros sepan que la versión del marco es limitada. –
Puede definir su propia clase MyTransaction como un contenedor alrededor de SqlTransaction. Mantenga una instancia de SqlTransaction en un campo privado dentro de MyTransaction. Su contenedor no será compatible con SqlTransaction, pero si implementa las mismas interfaces que SqlTransaction implementa, puede acercarse mucho.
Pensé que esto funcionaría también pero luego tienes algo como SqlClient.SQLCommand.Transaction que quiere SqlTransaction, no IDbTransaction que realmente es sux, así que necesito alguna forma de falsear esto que inició esta búsqueda ... – Denis
No, no puede hacer que su clase personalizada sea heredada de SqlTransaction o que la falsifiquen.
Sin embargo, si el contexto de lo que está haciendo le permite utilizar una DbTransaction, podría heredar su clase de transacción personalizada de DbTransaction, terminando una SqlTransaction dentro con cualquier otra funcionalidad que requiera.
Pensé que esto funcionaría también, pero luego tienes algo como SqlClient.SQLCommand.Transaction que quiere SqlTransaction – Denis
Sí , te metes en un montón de objetos envueltos ... puedes usar todo el envoltorio personalizado del espacio de nombres System.Data que envuelve las versiones SQL ... todo depende de cuáles sean tus requisitos y por qué estás jugando con estos objetos en el primer lugar. Es probable que haya otras (mejores) formas de lograr el objetivo. –
Haces tiene otra opción, puede usar Reflection.Emit() para agregar una interfaz de su elección a SqlTransaction, y luego usar esa misma interfaz, en su nueva clase MyTransaction y luego puede hacer llamadas a la interfaz, en lugar de la clase.
Tenga cuidado de que esto solo funcione en las bibliotecas que cree, o modifique específicamente los tipos cargados usando Reflection.
Además, esta es una solución particularmente sucia ... –
Nunca he intentado Reflection.Emit(). Voy a mirar alrededor, pero ¿tiene algún buen ejemplo/tutorial sobre cómo funcionaría esto? – Denis
Puede crear métodos de extensión.
public static class SqlTransactionExtensions
{
public static void DoSomething(this SqlTransaction transaction, int myParameter)
{
// do something here
}
}
La clase debe ser estática. Coloque la palabra mágica this
delante del primer parámetro que debe ser del tipo de la clase que está extendiendo. También puedes extender interfaces. Si desea utilizar este método de extensión, debe tener un using namspace
con el espacio de nombre de esta clase de extensión, si no está definido en el mismo espacio de nombres en el que está trabajando.
A continuación, puede llamar al método de extensión como si fuera un método regular de SqlTransaction:
SqlTransaction t = new SqlTransaction();
t.DoSomething(5);
Esta es una buena idea que alguien propuso aquí también, pero hay 2 problemas con esto: (1) estoy usando .NET 2.0 y (2) si no estuviera usando .NET 2.0, ¿cómo usaría los métodos de extensión para crear objetos en creación de SqlTransaction? (Digamos que quiero rastrear quién creó este sqlTransaction o la hora en que se inició) – Denis
Crearía una clase de ayuda estática para las transacciones. Muy parecido a la clase de extensiones, pero sin la palabra clave 'this'. En lugar de llamar a los métodos con 't.DoSomething (5);', tendrá que llamarlos con 'TransactionsHelper.DoSomething (t, 5);'. Los métodos de extensión son en realidad solo azúcar sintáctico y no pueden hacer nada que no se pueda hacer con los métodos normales. –
OK, así descartar la herencia y se centra en la tarea que realmente quiere resolver (Basado en el comentario trapos).
He tenido éxito en el pasado al ejecutar todas las llamadas a través de una biblioteca auxiliar e implementar la lógica allí. En el pasado, he usado SqlHelper, que se publica en Microsoft Data Application Block. Este es un módulo fuente, que puede adaptar a sus necesidades. Puede agregar cualquier log u otra lógica que necesite.
También hace que el código sea muy legible. Puede hacer cosas como:
SqlHelper.ExecuteDataset()
de consultas que devuelven conjuntos de datos,
SqlHelper.ExecuteScalar()
para las consultas de la devolución de valores individuales,
SqlHelper.ExecuteNonQuery()
para los comandos que no tienen retornos (como INSERT
's).
etc.
- 1. ¿Hay alguna forma de detener la herencia automática de DataContext en Silverlight?
- 2. ¿Hay alguna forma de currying en C?
- 3. ¿Hay alguna forma de sobrecargar + = en python?
- 4. Herencia/jerarquías de interfaz en .Net: ¿hay una forma mejor?
- 5. ¿Hay alguna forma de sincronizar archivos gif?
- 6. ¿Hay alguna forma de 'resaltar' el código?
- 7. ¿Hay alguna forma de pasar el iPhone?
- 8. ¿Hay alguna forma de multirreproducir un SqlDataReader?
- 9. ¿Hay alguna forma de vincular Keyboard.FocusedElement?
- 10. ¿Hay alguna forma de cancelar TabControl.Items.CurrentChanging?
- 11. ¿Hay alguna forma mejor de escribir esto?
- 12. ¿Hay alguna forma de escribir aplicaciones de Android en PHP?
- 13. ¿Hay alguna forma de restaurar ventanas de búfer en Emacs?
- 14. Cómo falsificar ip en java
- 15. ¿Hay alguna forma de reproducir mp3 en Qt 4.5?
- 16. ¿Hay alguna forma de actualizar automáticamente la aplicación en Android?
- 17. ¿Hay alguna forma de bloquear un proceso en una CPU?
- 18. ¿Hay alguna forma de regexp-quote una cadena en Node.js?
- 19. ¿Hay alguna forma de fundición "tipo segura" en Java?
- 20. ¿Hay alguna forma de detectar un lenguaje RTL en Java?
- 21. ¿Hay alguna forma de deshacer mi última inserción en Git?
- 22. En Heroku, ¿hay alguna forma de agregar múltiples anzuelos HTTP?
- 23. ¿Hay alguna forma de saltear solo una prueba en maven?
- 24. ¿Hay alguna forma de detectar SMS en E-Mail Gateways?
- 25. ¿Hay alguna forma de comunicarse con dispositivos USB en Android?
- 26. ¿Hay alguna forma de crear estructuras anónimas en C#?
- 27. ¿Hay alguna forma de copiar diagramas en diferentes proyectos?
- 28. ¿Hay alguna forma de crear múltiples activadores en un script?
- 29. En VS2008, ¿hay alguna forma de "adjuntar al proceso" automáticamente?
- 30. ¿Hay alguna forma de activar/desactivar restricciones en db2 v7?
'Supongamos que quiero heredar de System.Data.SqlClient.SqlTransaction' => ¿por qué querrías hacer algo como esto? –
Darin tiene razón; estás pidiendo un taladro en lugar de decirnos por qué necesitas un agujero en esa viga de acero en primer lugar. El hecho de que el tipo esté sellado es una gran bandera roja que dice NO QUIERO QUE SE HEREDA DE ESTO. ¿Por qué intentas trabajar en contra de los deseos del diseñador de la clase? Ellos tienen tus mejores intereses en el corazón. Explique lo que realmente quiere lograr, porque heredar de una clase sellada no va a suceder. –
¿No es posible desbloquear una clase usando reflexión? –