Пользовательский манипулятор для C++ iostream

Как предложил @ZorgoZ, я добавил всю запись в фильтр действий.

LogActionFilter.cs:

using Sample.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Sample.Filters
{
public class LogActionFilter : ActionFilterAttribute
{
    private readonly LogEntities _db = new LogEntities();

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       String originalPath = new Uri(HttpContext.Current.Request.Url.AbsoluteUri).OriginalString;
        var inputUser = ConfigurationManager.AppSettings["INPUT_USER"].ToString().ToLower();

        Log log = new Log();
        {
            log.Date = DateTime.Now;
            log.URL= originalPath;
            log.UserName = inputUser;
            _db.UserLogs.Add(log);
            _db.Entry(log).State = EntityState.Added;
            _db.SaveChanges();
        }
        base.OnActionExecuting(filterContext);
    }
}

}

Но у меня есть еще одна проблема. У меня есть еще один класс контроллера API. когда я пытаюсь получить доступ к API сотрудника через этот http: // localhost: 53037 / api / employee / 4 , мой фильтр действий не выполняется. Может кто-нибудь сказать мне, что я могу упустить или какие изменения мне нужно сделать?

EmployeeController.cs:

using Sample.Filters;
using Sample.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace Sample.Controllers
 {
public class EmployeeController : ApiController
{
    private readonly LogEntities _db = new LogEntities();

    [LogActionFilter]
    public IEnumerable Get()
    {
        using(EmployeeDBEntities entities = new EmployeeDBEntities())
        {
            return entities.Employees.ToList();
        }
    }

    [LogActionFilter]
    public Employee Get(int id)
    {
        using (EmployeeDBEntities entities = new EmployeeDBEntities())
        {

            return entities.Employees.FirstOrDefault(e => e.ID == id);
        }
    }

    [LogActionFilter]
    public void Post([FromBody] Employee employee)
    {
        using (EmployeeDBEntities entities = new EmployeeDBEntities())
        {
            entities.Employees.Add(employee);
            entities.SaveChanges();
        }
    }
}
 }

Главный контроллер:

using Sample.Filters;
using Sample.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace Sample.Controllers
 {
public class HomeController : Controller
{

    public ActionResult Index()
    {
        return View();
    }
    [LogActionFilter]
    public ActionResult About(UserLog usr)
    {
        ViewBag.Message = "Your application description page.";
        return View();

    }
    [LogActionFilter]
    public ActionResult Contact()
    {
        ViewBag.Message = "Your contact page.";

        return View();
    }
}

} [ 1110]

11
задан nvunguyen 11 February 2009 в 04:34
поделиться

4 ответа

Особенно трудно добавить манипулятор к потоку C++, поскольку каждый не имеет никакого контроля над тем, как манипулятор используется. Можно пропитать новую локаль в поток, которому установили фасет, который управляет, как числа печатаются - но не, как производятся строки. И затем проблема все еще состояла бы в том, как сохранить состояние заключения в кавычки безопасно в поток.

Строки производятся с помощью оператора, определенного в std пространство имен. Если Вы хотите изменить способ, которым они печатаются, все же сохраняя вид манипуляторов, можно создать прокси-класс:

namespace quoting {
struct quoting_proxy {
    explicit quoting_proxy(std::ostream & os):os(os){}

    template<typename Rhs>
    friend std::ostream & operator<<(quoting_proxy const& q, 
                                     Rhs const& rhs) {
        return q.os << rhs;
    }

    friend std::ostream & operator<<(quoting_proxy const& q, 
                                     std::string const& rhs) {
        return q.os << "'" << rhs << "'";
    }

    friend std::ostream & operator<<(quoting_proxy const& q, 
                                     char const* rhs) {
        return q.os << "'" << rhs << "'";
    }
private:
    std::ostream & os;
};

struct quoting_creator { } quote;
quoting_proxy operator<<(std::ostream & os, quoting_creator) {
    return quoting_proxy(os);
}
}

int main() {
    std::cout << quoting::quote << "hello" << std::endl; 
}

Который подошел бы, чтобы использоваться для ostream. Если Вы хотите сделать вывод, можно сделать это шаблоном также и также принять basic_stream вместо плоскости string. Это имеет различные поведения стандартным манипуляторам в некоторых случаях. Поскольку это работает путем возврата объекта прокси, это не будет работать на случаи как

std::cout << quoting::quote; 
std::cout << "hello";
18
ответ дан 3 December 2019 в 02:30
поделиться

Попробуйте это:

#include <iostream>
#include <iomanip>

// The Object that we put on the stream.
// Pass in the character we want to 'quote' the next object with.
class Quote
{
    public:
        Quote(char x)
            :m_q(x)
        {}
    private:
        // Classes that actual does the work.
        class Quoter
        {
            public:
                Quoter(Quote const& quote,std::ostream& output)
                    :m_q(quote.m_q)
                    ,m_s(output)
                {}

                // The << operator for all types. Outputs the next object
                // to the stored stream then returns the stream. 
                template<typename T>
                std::ostream& operator<<(T const& quoted)
                {
                    return m_s << m_q << quoted << m_q;
                }

            private:
                char            m_q;
                std::ostream&   m_s;
        };
        friend Quote::Quoter operator<<(std::ostream& str,Quote const& quote);

    private:
        char    m_q;
};

// When you pass an object of type Quote to an ostream it returns
// an object of Quote::Quoter that has overloaded the << operator for
// all types. This will quote the next object and the return the stream
// to continue processing as normal.
Quote::Quoter operator<<(std::ostream& str,Quote const& quote)
{
    return Quote::Quoter(quote,str);
}


int main()
{
    std::cout << Quote('"') << "plop" << std::endl;
}
7
ответ дан 3 December 2019 в 02:30
поделиться

[РЕДАКТИРОВАНИЕ: "Истинная семантика манипулятора" (т.е. персистентное состояние заключения в кавычки) могла также быть достигнута путем обертывания std::ostream вместо того, чтобы происходить из него, как отмечено Benôit в комментариях.]

Насколько я знаю это не может быть сделано непосредственно ни без одного получения нового класса от std::ostream или подобный, или обертывание такого класса в другом классе, что вперед большинство методов к его содержавшему std::ostream объект. Поэтому, для примера кода Вы обеспечиваете к работе, необходимо будет так или иначе изменить поведение std::ostream& operator<<(std::ostream&, std::string const&), который определяется где-нибудь в iostreams иерархии (или возможно везде, где std::string определяется). Необходимо будет также использовать (несколько ужасные) средства в ios_base записывать булев флаг, содержащий текущее состояние заключения в кавычки. Искать ios_base::xalloc(), ios_base::iword() и ios_base::pword() узнать, как сделать это.

Однако, если Вы готовы использовать следующий синтаксис:

os << "SELECT * FROM customers WHERE name = " << quote(name);

Это может быть сделано очень просто с помощью глобальной функции (в соответствующем пространстве имен, конечно).

Этот синтаксис имеет преимущество, что заключение в кавычки не является персистентным, означая, что это не может "просочиться", когда функция устанавливает quote форматирование флага и забывает задерживать его к своему исходному значению.

6
ответ дан 3 December 2019 в 02:30
поделиться

Или просто используйте OTL, который в основном уже реализует потоковый интерфейс для SQL очень похоже к Вашему примеру.

1
ответ дан 3 December 2019 в 02:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: