Mocking PrintQueue in .NET - c#

There is a need to mock System.Printing.PrintQueue for some test. Currently I'm getting this error when trying to create PrintQueue for presumably existing virtual printer (new PrintQueue(new PrintServer(), "Microsoft XPS Document Writer")):
System.Printing.PrintQueueException: PrintTicket provider failed to bind to printer. Win32 error: -2147467231
at MS.Internal.Printing.Configuration.PTProvider..ctor(String deviceName, Int32 maxVersion, Int32 clientVersion)
at MS.Internal.Printing.Configuration.PTProviderBase.Create(String deviceName, Int32 maxVersion, Int32 clientVersion)
at System.Printing.PrintTicketManager..ctor(String deviceName, Int32 clientPrintSchemaVersion)
at System.Printing.PrintQueue.GetPrintCapabilities()
Note the error is not about missing printer.
I can shim PrintTicket that is on the top of stack using Fakes, but it's absolutely not clear which method is throwing. And PrintQueue is not a managed class (resides in PrintQueue.cpp). Any ideas?
edit
Googled around a bit, still no luck getting around this issue:
https://connect.microsoft.com/VisualStudio/feedback/details/690455/printqueue-getprintcapabilities-throws-when-incorrect-driver-is-configured-for-printer-on-print-server
http://www.infragistics.com/community/forums/t/50736.aspx
http://petterisbetter.com/michael/index.php/2008/09/29/printticket-provider-failed-to-retrieve-

Solving the problem required extracting and implementing a few "partial" interfaces.
/// <summary>
/// Contract for PrintCapabilities
/// </summary>
public interface IPrintCapabilities
{
/// <summary>
/// Gets CollactionCapability.
/// </summary>
IEnumerable<Collation> CollationCapability { get; }
/// <summary>
/// Gets MaxCopyCount.
/// </summary>
int? MaxCopyCount { get; }
/// <summary>
/// Gets OrientedPageMediaHeight.
/// </summary>
double? OrientedPageMediaHeight { get; }
/// <summary>
/// Gets OrientedPageMediaWidth.
/// </summary>
double? OrientedPageMediaWidth { get; }
/// <summary>
/// Gets PageMediaSizeCapability.
/// </summary>
IEnumerable<PageMediaSize> PageMediaSizeCapability { get; }
/// <summary>
/// Gets PageOrientationCapability.
/// </summary>
IEnumerable<PageOrientation> PageOrientationCapability { get; }
/// <summary>
/// Gets DuplexingCapability.
/// </summary>
IEnumerable<Duplexing> DuplexingCapability { get; }
/// <summary>
/// Gets InputBinCapability.
/// </summary>
IEnumerable<InputBin> InputBinCapability { get; }
/// <summary>
/// Gets OutputColorCapability.
/// </summary>
IEnumerable<OutputColor> OutputColorCapability { get; }
/// <summary>
/// Gets PageOrderCapability.
/// </summary>
IEnumerable<PageOrder> PageOrderCapability { get; }
/// <summary>
/// Gets StaplingCapability.
/// </summary>
IEnumerable<Stapling> StaplingCapability { get; }
}
/// <summary>
/// Contract for PrintQueue
/// </summary>
public interface IPrintQueue
{
/// <summary>
/// Gets IsOffline flag.
/// </summary>
bool IsOffline { get; }
/// <summary>
/// Gets FullName.
/// </summary>
string FullName { get; }
/// <summary>
/// Refreshes PrintQueue.
/// </summary>
void Refresh();
/// <summary>
/// Gets or sets DefaultPrintTicket.
/// </summary>
IPrintTicket DefaultPrintTicket { get; set; }
/// <summary>
/// Gets PrintCapabilities.
/// </summary>
/// <returns></returns>
IPrintCapabilities GetPrintCapabilities();
}
/// <summary>
/// Contract for PrintQueueCollection.
/// </summary>
public interface IPrintQueueCollection : IEnumerable
{
}
/// <summary>
/// Interface that describes all classes implementing PrintServer operations.
/// </summary>
public interface IPrintServer
{
/// <summary>
/// Gets the collection of print queues of the specific types.
/// </summary>
/// <param name="enumerationFlag">Array of types of print queues.</param>
/// <returns>Print queues collection.</returns>
IPrintQueueCollection GetPrintQueues(EnumeratedPrintQueueTypes[] enumerationFlag);
/// <summary>
/// Returns a reference of default print queue of LocalPrintServer.
/// </summary>
/// <returns>Print queue.</returns>
IPrintQueue GetDefaultPrintQueue();
}
/// <summary>
/// Contract for PrintTicket
/// </summary>
public interface IPrintTicket
{
/// <summary>
/// Gets or sets PageOrientation.
/// </summary>
PageOrientation? PageOrientation { get; set; }
/// <summary>
/// Gets or sets Duplexing.
/// </summary>
Duplexing? Duplexing { get; set; }
/// <summary>
/// Gets or sets Stapling.
/// </summary>
Stapling? Stapling { get; set; }
/// <summary>
/// Gets or sets PageOrder.
/// </summary>
PageOrder? PageOrder { get; set; }
/// <summary>
/// Gets or sets OutputColor.
/// </summary>
OutputColor? OutputColor { get; set; }
/// <summary>
/// Gets or sets Collation.
/// </summary>
Collation? Collation { get; set; }
/// <summary>
/// Gets or sets PageMediaSize.
/// </summary>
PageMediaSize PageMediaSize { get; set; }
}

Related

Column sortorder when writing CSV file using CsvHelper

When writing TSVs from .Net objects file using CsvHelper, I would like to control column sort order using attributes.
When using the CsvHelper-provided Index(..) attribute, I am able to control serialization order, but the column header is suffixed with an index:
Model(s), inherited:
/// <summary>
/// Generic daily data
/// </summary>
public class DailyData
{
/// <summary>
///
/// </summary>
[CsvHelper.Configuration.Attributes.Index(-2, -2)]
public int IdDay {get;set;}
}
/// <summary>
/// Generic hou-on-a-day data
/// </summary>
public class HourlyData : DailyData
{
/// <summary>
///
/// </summary>
[CsvHelper.Configuration.Attributes.Index(-1)]
public byte IdHour { get; set; }
}
/// <summary>
///
/// </summary>
public class HourlyWeatherInfo : HourlyData
{
/// <summary>
///
/// </summary>
public double Temperature { get; internal set; }
}
Output:
IdDay1 IdHour1 Temperature
20220516 18 291.7
20220516 21 289.55
20220517 0 287.3
20220517 3 286.33
I am using negative numbers for indices because I want the base class to have their properties listed first without having to bother with serialization order in the derived classes (like HourlyWeatherInfo.
Am I overlooking functionality?
It feels a bit hacky, but this seems to work.
/// <summary>
/// Generic daily data
/// </summary>
public class DailyData
{
/// <summary>
///
/// </summary>
[CsvHelper.Configuration.Attributes.Index(-2,-3)]
public int IdDay {get;set;}
}
/// <summary>
/// Generic hou-on-a-day data
/// </summary>
public class HourlyData : DailyData
{
/// <summary>
///
/// </summary>
[CsvHelper.Configuration.Attributes.Index(-1,-2)]
public byte IdHour { get; set; }
}
/// <summary>
///
/// </summary>
public class HourlyWeatherInfo : HourlyData
{
/// <summary>
///
/// </summary>
public double Temperature { get; internal set; }
}

Setting up naming rules for Web API model classes using Swagger

Good afternoon.
I have the following controller method:
/// <summary>
/// Метод создания вида работ
/// </summary>
/// <param name="name">Название вида работ</param>
/// <param name="workUnitId">ИД единицы вида работ</param>
/// <returns>Результат создания вида работ</returns>
[Route(nameof(CreateWorkType))]
[HttpPost]
public async Task<ActionResult<DtoResult<DtoWorkType>>> CreateWorkType(string name, Guid? workUnitId = null)
{
try
{
var result = await _workTypeService.CreateWorkType(name, workUnitId).ConfigureAwait(false);
return Ok(result);
}
catch
{
return BadRequest($"Ошибка при выполнении создания вида работ с именем \"{name}\" и ИД единицы работ \"{workUnitId}\"");
}
}
The method used is the generic class DtoResult:
/// <summary>
/// Класс результат
/// </summary>
/// <typeparam name="T">Тип данных сущности</typeparam>
public class DtoResult<T> where T : class, new()
{
#region Свойства
/// <summary>
/// Результат проверки сущности типа данных <see cref="T"/>
/// </summary>
public DtoValidationResult Validation { get; set; } = new DtoValidationResult();
/// <summary>
/// Данные сущности типа данных <see cref="T"/>
/// </summary>
public T Data { get; set; } = new T();
#endregion
}
"Business" сlass DtoWorkType:
/// <summary>
/// Класс вида работ
/// </summary>
public class DtoWorkType
{
#region Свойства
/// <summary>
/// ИД вида работ
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Название вида работ
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// Единица работ для вида работ
/// </summary>
public DtoWorkUnit WorkUnit { get; set; } = new DtoWorkUnit();
#endregion
}
Using Swagger, a class named DtoWorkTypeDtoResult was automatically created.
Question:
Is it possible to use the SWAGGER configuration tools or other mechanisms to determine the name of the class, for example, using the following algorithm:
$"{nameof(T)}Result"
for the class to have the following name: DtoWorkTypeResult
not like now: DtoWorkTypeDtoResult
You can use the method CustomSchemaIds to configure the swagger:
services.AddSwaggerGen(c =>
{
//other code
c.CustomSchemaIds(p => p.Name);
});

Web API Help page doesn't show documentation of extended object

Tldr;
I have a object that extends from another object.
/// <summary>
/// Represents the result of an operation
/// </summary>
[DataContract]
public class ApiResult<T> : ApiResult
{
/// <summary>
/// The requested data
/// </summary>
[DataMember]
public T Data { get; private set; }
/// <summary>
/// Test
/// </summary>
[DataMember]
public string Test { get; private set; }
Every property of ApiResult is documented, but not the properties of ApiResult<T>:
Why is the documentation description blank for a extended object? I expected that my <summary> is used here. How can I make it show?
More Details
Here is the full code:
/// <summary>
/// Represents the result of an operation
/// </summary>
//[DataContract(Name = "ApiResult")]
public class ApiResult
{
/// <summary>
/// Indicates if the operation was performed successfull. If an error occured more Information are available in ErrorCode and Message.
/// </summary>
[DataMember]
public bool IsSuccess { get; private set; }
/// <summary>
/// A programmable static reason, if the operation was not successfull. This can be ignored on successfull state.
/// </summary>
[DataMember]
public int ErrorCode { get; private set; }
/// <summary>
/// Additional information about the error, if the operation was not successfull. This is only for Information purpose. Use the ErrorCode for business conditions instead.
/// </summary>
[DataMember]
public string Message { get; private set; }
/// <summary>
/// Creates a Success Result
/// </summary>
public ApiResult()
{
IsSuccess = true;
ErrorCode = 0;
Message = "ok";
}
/// <summary>
/// Creates a Error Result
/// </summary>
/// <param name="errorCode">The error code</param>
/// <param name="message">The message</param>
public ApiResult(int errorCode, string message)
{
IsSuccess = false;
ErrorCode = errorCode;
Message = message;
}
}
/// <summary>
/// Represents the result of an operation
/// </summary>
//[DataContract(Name = "ApiResult")]
public class ApiResult<T> : ApiResult
{
/// <summary>
/// The requested data
/// </summary>
[DataMember]
public T Data { get; private set; }
/// <summary>
/// Test
/// </summary>
[DataMember]
public string Test { get; private set; }
/// <summary>
/// Creates a Success Result without having an actualy Result
/// <remarks>This constructor should not be used. A parameterless constructor is needed for the automatic generation of a Documentation Example.</remarks>
/// </summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//[Obsolete("Use the nongeneric version of ApiResult instead. This CTOR is only to support XmlSerialization.")]
public ApiResult()
{
}
/// <summary>
/// Creates a Success Result
/// </summary>
/// <param name="data">The data</param>
public ApiResult(T data)
{
Data = data;
}
/// <summary>
/// Creates a Error Result
/// </summary>
/// <param name="errorCode">The error code</param>
/// <param name="message">The message</param>
public ApiResult(int errorCode, string message) : base(errorCode, message)
{
}
}
And here my Method signature:
public ApiResult<CardInfo> GetCardInfo(string cardNumber)
Just in case, here is my CardInfo-class:
/// <summary>
/// Information about a card
/// </summary>
public class CardInfo
{
/// <summary>
/// Card Type
/// </summary>
public string CardType { get; set; }
/// <summary>
/// Represents the current credit on card.
/// Prepaid cards: CurrentValue represents the current credit on card.
/// Postpaid: CurrentValue represents the monthly available credit amount.
/// </summary>
public decimal CurrentValue { get; set; }
}
My Question is about the automatic generated Help Page in Web API 2. The <summary> is ignored on the helppage, if the Class is extended.

How can i take only the true property from a class

I have a class with 6 property:
public class ControllerValuesArgs:EventArgs
{
// debouncer for button
private static int btnCounter = 0;
// flag to send buttons
bool activeFlag = false;
/// <summary>
/// Default constructor.
/// </summary>
public ControllerValuesArgs()
{
// Reset buttons to initial state
ResetButtons();
}
/// <summary>
/// Gets or sets state of button 1.
/// </summary>
public bool Button1Pressed
{
get;
set;
}
/// <summary>
/// Gets or sets state of button 2.
/// </summary>
public bool Button2Pressed
{
get;
set;
}
/// <summary>
/// Gets or sets state of button 3.
/// </summary>
public bool Button3Pressed
{
get;
set;
}
/// <summary>
/// Gets or sets state of button 4.
/// </summary>
public bool Button4Pressed
{
get;
set;
}
/// <summary>
/// Gets or sets state of button 5.
/// </summary>
public bool Button5Pressed
{
get;
set;
}
/// <summary>
/// Gets or sets state of button 6.
/// </summary>
public bool Button6Pressed
{
get;
set;
}
I want to use the the property with true result inside to put it in a hashtable and converted to string.
What i try:
/// <summary>
/// Handler listening on Conontroller variables needed to calculate the expression.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">An object that contains no event data.</param>
public void ConontrollerValuesUpdate(object sender, EventArgs e)
{
ControllerValuesArgs conontrollerValuesArgs = new ControllerValuesArgs();
hashtable["UserInput"] = conontrollerValuesArgs.ToString();
CalculateExpression();
}
How can i call ore search for the true result in all property from that class and put it in the table?
This is similar to converting any object to ExpandoObject as ExpandObject implements IDictionary<string,object>.
This should give you dictionary with properties.
public static class DynamicExtensions
{
public static IDictionary<string, object> ToDynamicDictionary(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
return expando;
}
}
Answer based on http://blog.jorgef.net/2011/06/converting-any-object-to-dynamic.html

How to create criteria query for given sql query

I am creating an ICriteria query for this equivalent sql query.
SELECT fCustomerID,
ISNULL(
(SELECT SUM(payinv.fAmount) AS Expr1
FROM dbo.tARPayment AS pay
INNER JOIN dbo.tARPaymentInvoice AS payinv ON pay.fPaymentID = payinv.fPaymentID
INNER JOIN dbo.tARInvoice AS inv ON payinv.fInvoiceID = inv.fARInvoiceID
WHERE (pay.fIsPosted = CASE pay.fPaymentType WHEN 'CM' THEN 0 WHEN 'EPD' THEN 0 ELSE 1 END)
AND (inv.fCustomerID <> dbo.tARCustomer.fCustomerID)
AND (pay.fCustomerID = dbo.tARCustomer.fCustomerID)), 0)
FROM dbo.tARCustomer
GROUP BY fCustomerID
But I am not getting anyway that how can I generate equivalent nhibernate ICriteria query.
This is payment class
public partial class tARPayment
{
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="tARPayment"/> class.
/// </summary>
public tARPayment()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="tARPayment"/> class.
/// </summary>
/// <param name="fPaymentID">The fPaymentID of guid type.</param>
public tARPayment(System.Guid fPaymentID)
{
this.ID = fPaymentID;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets payment id.
/// </summary>
public virtual System.Guid fPaymentID { get; set; }
/// <summary>
/// Gets or sets fCustomerID.
/// </summary>
public virtual System.Guid fCustomerID { get; set; }
/// <summary>
/// Gets or sets check number.
/// </summary>
public virtual string fCheckNumber { get; set; }
/// <summary>
/// Gets or sets amount.
/// </summary>
public virtual decimal fAmount { get; set; }
/// <summary>
/// Gets or sets customer detail.
/// </summary>
public virtual tARCustomer Customer { get; set; }
public virtual IList<tARPaymentInvoice> PaymentInvoices { get; set; }
#endregion
#region Methods
/// <summary>
/// partial class for payment.
/// </summary>
/// <returns>The method get code.</returns>
public override int GetHashCode()
{
return ID.GetHashCode();
}
#endregion
}
This is a invoice class
public partial class tARInvoice
{
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="tARInvoice"/> class.
/// </summary>
public tARInvoice()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="tARInvoice"/> class.
/// </summary>
/// <param name="fARInvoiceID">The fARInvoiceID.</param>
public tARInvoice(System.Guid fARInvoiceID)
{
this.ID = fARInvoiceID;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets fARInvoiceID.
/// </summary>
public virtual Guid fARInvoiceID { get; set; }
/// <summary>
/// Gets or sets fCustomerID.
/// </summary>
public virtual Guid fCustomerID { get; set; }
/// <summary>
/// Gets or sets Delivery Method.
/// </summary>
public virtual string fDeliveryMethod { get; set; }
/// <summary>
/// Gets or sets Invoice Number.
/// </summary>
public virtual int? fARInvoiceNumber { get; set; }
public virtual tARCustomer Customer { get; set; }
public virtual IList<tARPaymentInvoice> PaymentInvoices { get; set; }
#endregion
#region Methods
/// <summary>
/// retrieve Hash Code.
/// </summary>
/// <returns>The method get code.</returns>
public override int GetHashCode()
{
return ID.GetHashCode();
}
#endregion
}
This is a payment invoice class.
public partial class tARPaymentInvoice
{
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="tARPaymentInvoice"/> class.
/// </summary>
public tARPaymentInvoice()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="tARPaymentInvoice"/> class.
/// </summary>
/// <param name="fPaymentInvoiceID">The Invoice ID.</param>
public tARPaymentInvoice(System.Guid fPaymentInvoiceID)
{
this.ID = fPaymentInvoiceID;
}
#endregion
#region Properties
/// <summary>
/// Gets or sets fPaymentInvoiceID.
/// </summary>
public virtual System.Guid fPaymentInvoiceID { get; set; }
/// <summary>
/// Gets or sets fPaymentID.
/// </summary>
public virtual System.Guid fPaymentID { get; set; }
/// <summary>
/// Gets or sets fInvoiceID.
/// </summary>
public virtual System.Guid fInvoiceID { get; set; }
/// <summary>
/// Gets or sets tARPayment.
/// </summary>
public virtual tARPayment Payment { get; set; }
/// <summary>
/// Gets or sets tARInvoice.
/// </summary>
public virtual tARInvoice Invoice { get; set; }
#endregion
#region Methods
/// <summary>
/// get hash codes.
/// </summary>
/// <returns>The hash code.</returns>
public override int GetHashCode()
{
return ID.GetHashCode();
}
#endregion
}
Rather than converting the above query to LINQ or HQL, I would recommend making the query into a view, and then using NHibernate to query that view.
SQL
CREATE VIEW vCustomerAmount AS
SELECT fCustomerID,
ISNULL(
(SELECT SUM(payinv.fAmount) AS Expr1
FROM dbo.tARPayment AS pay
INNER JOIN dbo.tARPaymentInvoice AS payinv ON pay.fPaymentID = payinv.fPaymentID
INNER JOIN dbo.tARInvoice AS inv ON payinv.fInvoiceID = inv.fARInvoiceID
WHERE (pay.fIsPosted = CASE pay.fPaymentType WHEN 'CM' THEN 0 WHEN 'EPD' THEN 0 ELSE 1 END)
AND (inv.fCustomerID <> dbo.tARCustomer.fCustomerID)
AND (pay.fCustomerID = dbo.tARCustomer.fCustomerID)), 0) [Amount]
FROM dbo.tARCustomer
GROUP BY fCustomerID
C# DTO
public class CustomerAmount
{
public int fCustomerID { get; set; }
public decimal Amount { get; set; }
}
Query
List<CustomerAmount> customerAmounts = session.Query<CustomerAmount>().ToList();
Not sure about nHibernate, but does this rewritten query help get the same answer and is something you can run with easier?
SELECT T.fCustomerID,
coalesce( SUM( payinv.fAmount ), 0 ) as SumAmt
FROM
dbo.tARCustomer T
JOIN dbo.tARPayment AS pay
ON T.fCustomerID = pay.fCustomerID
AND pay.fIsPosted = CASE pay.fPaymentType
WHEN 'CM' THEN 0
WHEN 'EPD' THEN 0
ELSE 1 END
JOIN dbo.tARPaymentInvoice AS payinv
ON pay.fPaymentID = payinv.fPaymentID
INNER JOIN dbo.tARInvoice AS inv
ON payinv.fInvoiceID = inv.fARInvoiceID
AND inv.fCustomerID <> T.fCustomerID
GROUP BY
T.fCustomerID

Categories

Resources