无法将记录器向下转换回原始结构

问题描述 投票:0回答:1

我想访问我的

log::Log
impl 实例以访问特定字段,但是一旦我收到引用,我就无法将其向下转换为我的结构。

我尝试将记录器引用转换为

core::any::Any
,然后将其向下转换为我的原始结构,但我总是获得
None

use core::any::Any;

pub trait AToAny: 'static {
    fn as_any(&self) -> &dyn Any;
}

impl<T: 'static> AToAny for T {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

struct MyLogger {}

impl log::Log for MyLogger {
    fn enabled(&self, _: &log::Metadata<'_>) -> bool { todo!() }
    fn log(&self, _: &log::Record<'_>) { todo!() }
    fn flush(&self) { todo!() }
}

pub fn main() {
    let logger_impl = MyLogger {};
    log::set_boxed_logger(Box::new(logger_impl)).unwrap();
    let logger = log::logger();
    
    let logger_any = logger.as_any();
    let logger_impl = logger_any.downcast_ref::<MyLogger>()
        .expect("downcast failed");
}

我也尝试过不通过日志初始化函数传递,但我得到了相同的结果:

use core::any::Any; // 0.10.1

pub trait AToAny: 'static {
    fn as_any(&self) -> &dyn Any;
}

impl<T: 'static> AToAny for T {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

struct MyLogger {}

impl log::Log for MyLogger {
    fn enabled(&self, _: &log::Metadata<'_>) -> bool { todo!() }
    fn log(&self, _: &log::Record<'_>) { todo!() }
    fn flush(&self) { todo!() }
}

pub fn main() {
    let logger_impl = MyLogger {};
    let logger_boxed: Box<MyLogger> = Box::new(logger_impl);
    let logger: &'static mut dyn log::Log = Box::leak(logger_boxed);
    
    let logger_any = logger.as_any();
    let logger_impl = logger_any.downcast_ref::<MyLogger>()
        .expect("downcast failed");
}

这是操场上的代码

我看到

type_id
变量的
logger
type_id
logger_impl
不同,所以我相信这就是阻止我进行沮丧的原因,但我无法理解我应该如何做解决这个问题。

rust traits downcast
1个回答
0
投票

您正在调用

<&dyn Log>::as_any
,但您只能将其向下转换为
&dyn Log
。 A
&dyn Log
不会暴露向下转换为
MyLogger
所需的信息。

幸运的是,您在这里根本不需要

Any
或向下转型,因为您可以仅使用共享引用来设置全局记录器:

struct MyLogger {}
impl MyLogger {
    fn foo(&self) {
        println!("foo")
    }
}
pub fn main() {
    let logger: &MyLogger = Box::leak(Box::new(MyLogger {}));
    log::set_logger(logger as &dyn log::Log).unwrap();
    logger.foo(); // can still call inherent MyLogger::foo
}
© www.soinside.com 2019 - 2024. All rights reserved.